coral_config_arguments
coral_config_options
coral_config_command
coral_config_file
coral_usage
coral_config_defaults
coral_set_api
coral_set_max_sources
,
coral_get_max_sources
coral_set_options
,
coral_get_options
coral_set_iomode
coral_get_iomode
coral_set_errfile
,
coral_set_errfilename
,
coral_get_errfile
coral_set_verbosity
,
coral_get_verbosity
coral_set_max_pkts
,
coral_set_max_cells
,
coral_set_max_blks
,
coral_get_max_pkts
,
coral_get_max_cells
,
coral_get_max_blks
coral_set_skip_pkts
,
coral_get_skip_pkts
coral_set_comment
,
coral_get_comment
coral_set_duration
,
coral_get_duration
coral_set_interval
,
coral_get_interval
coral_set_dropinterval
,
coral_get_dropinterval
coral_set_mintime
,
coral_get_mintime
,
coral_set_maxtime
,
coral_get_maxtime
coral_set_gzip
coral_new_source
coral_new_fdsource
coral_source_set_iomode
,
coral_source_set_iomode_all
coral_source_get_iomode
,
coral_iface_get_iomode
coral_format_iomode
coral_source_set_firmware
,
coral_source_set_firmware_all
coral_open
,
coral_open_all
coral_start
,
coral_start_all
coral_stop_all
,
coral_stop
coral_close_all
,
coral_close
coral_get_iface_stats
coral_pkt_done
coral_pkt_atm_hook
coral_get_payload
coral_fmt_get_payload
coral_get_payload_by_proto
,
coral_get_payload_by_layer
coral_pkt_truncate
coral_get_net_pkt
coral_field_fits
coral_add_pcap_filter
,
coral_add_pcap_prefilter
,
coral_add_pcap_ipfilter
coral_get_pcap_filter
,
coral_get_pcap_prefilter
,
coral_get_pcap_ipfilter
coral_pcap_compile
,
coral_pcap_setfilter
,
coral_pcap_setprefilter
coral_get_anonymizer
coral_set_anonymizer
coral_anonymize_ip4
,
coral_anonymize_ip6
coral_anonymize
coral_pkt_anonymize
coral_read_cell
,
coral_read_cell_all
coral_read_cell_i
,
coral_read_cell_all_i
coral_read_block
,
coral_read_block_all
coral_file_version
coral_next_interface
,
coral_next_source
coral_next_src_iface
coral_source_get_filename
coral_source_get_name
coral_source_get_comment
coral_get_source_count
coral_interface_get_src
coral_interface_get_type
coral_source_get_type
coral_interface_get_datalink
coral_interface_get_physical
coral_interface_get_bandwidth
coral_source_get_number
,
coral_interface_get_number
coral_interface_get_capture_tv
coral_interface_get_capturetime
coral_cell_size
coral_read_clock_timespec
,
coral_read_clock_sec_nsec
,
coral_read_clock_double
,
CORAL_TIMESTAMP_TO_TIMEVAL
,
CORAL_TIMESTAMP_TO_TIMESPEC
coral_cell_time_double
coral_proto_abbr
,
coral_proto_desc
,
coral_proto_str
coral_dns_op_to_str
,
coral_dns_qtype_to_str
,
coral_dns_qclass_to_str
coral_dns_str_to_op
,
coral_dns_str_to_qtype
,
coral_dns_str_to_qclass
coral_proto_id
coral_proto_layer
coral_rf_open_fd
,
coral_rf_open_file
,
coral_rf_open_gzfile
,
coral_rf_open_ogzfile
,
coral_rf_open_pcap_dump
coral_rf_open
,
coral_rf_cb_open_filetype
,
coral_rf_cb_close_filetype
coral_rf_ogz_write
,
coral_rf_ogz_seek
,
coral_rf_ogz_flush
coral_rf_info
coral_rf_start
coral_rf_start_name
coral_rf_start_output
coral_rf_end
coral_rf_close
coral_rotate_errfile
coral_write_open
coral_write_rfopen
coral_write_fdopen
coral_write_get_name
coral_write_set_comment
,
coral_write_set_encoding
coral_write_init_all
,
coral_write_init_source
coral_write_init_interface
coral_write_cells
coral_write_block
coral_write_close
coral_iface_to_pcapp
,
coral_iface_to_pcapp_raw
coral_iface_to_pcap
coral_pkt_to_pcap
coral_write_pkt_to_pcap
coral_puts
coral_printf
coral_diag
coral_fprint_data
,
coral_print_data
coral_fprint_cell
,
coral_print_cell
coral_fmprint_pkt
coral_fprint_pkt
coral_mprint_pkt
,
coral_print_pkt
coral_fmt_if_subif
coral_fmt_subif
coral_dump
,
coral_dump_all
coral_stats
,
coral_stats_all
coral_filename
coral_inet_pton
coral_inet_ntop
coral_in_cksum_add
,
coral_in_cksum_result
coral_sendblk
Libcoral operates on "sources", which include several types of live network interfaces/devices, and several types of tracefiles containing data recorded from one or more network interfaces/devices. The naming scheme for sources is described in the command usage document.
A typical program using libcoral has this basic structure:
configure libcoral and one or more sources open sources start sources while (read block, cell or packet != NULL) { process the data we just read if (stop condition occurs) { stop sources } } close sources
In the descriptions below, there are several pairs of functions with the same base name, with or without an "_all" suffix. The function suffixed with "_all" operates on all sources, and the other one operates on a single source indicated by the src parameter.
All C/C++ programs built on CoralReef should include these headers:
#include <stdlib.h> #include <stdio.h> #include <sys/param.h> #include <libcoral.h>
Note that <libcoral.h>
will define
fixed-width integer types
(like uint32_t
) if your system does not, since they are needed
by many libcoral structures.
The following optional headers are also available:
#include <coral-config.h> /* configuration information used by coral */ #include <crl_byteorder.h> /* byte order macros */
CoralReef programs should link with -lcoral
,
-lpcap
(if libcoral was compiled with pcap support),
-lz
(if libcoral was compiled with zlib support), and
possibly -lstdc++
(if needed for Crypto-PAn),
in that order.
The installed Coral/lib/example/Makefile will link with the correct
set of libraries.
The following functions read coral commands from the command line or config files. The coral commands are described in the command usage document. These functions should only be called before coral_open() or coral_open_all().
You should call coral_set_api()
before calling these functions to enable certain configuration commands.
Also, you should set the defaults for configurable values with the
coral_set functions before calling any of these
functions, and (if needed) get the value after.
This way, the option and its default value will appear in the
coral_usage()
message, and the user can override the
defaults with command line options. If your application does not use a
particular configurable value, you should leave it set to its initial value,
so it will not appear in the coral_usage()
message,
and the coral_config functions will not allow it
to be changed on the command line.
int coral_config_arguments(int argc,
char *argv[]);
This function processes "-C
" options and sourcename arguments
contained in argv.
Argv is a pointer to an array
of strings containing the command line;
argc is the number of strings in argv.
For a description of Coral options, see the
Command Usage documentation.
A CoralReef source is created (with coral_new_source()
)
from each sourcename argument.
If an option syntax error is encountered, this function prints a usage message.
If other arguments are desired, use
coral_config_options()
instead
and parse the arguments yourself;
if other options are desired, parse the options and arguments yourself and call
coral_config_command()
for each "-C
" option.
Returns a non-negative integer for success, -1 for failure.
To limit the number of sources that will be allowed, call
coral_set_max_sources()
before calling this function.
For an example, see the end of this section.
int coral_config_options(int argc,
char *argv[],
const char *argmsg);
This function is like coral_config_arguments()
, except it
processes only the options, not the non-option arguments.
If argmsg is NULL
, this
function assumes that arguments (other than Coral options) are not allowed,
and considers it an error if other arguments are found;
otherwise, other arguments (but not other options) are allowed.
If successful, this function returns the index of the first non-option
argument (so it would return 1 if there were no options,
since argv[0]
is the application name).
It is the programmer's responsibility to handle
the remaining command line arguments.
If an error is encountered, this function returns -1, and prints a usage message
with coral_usage(argv[0], "%s", argmsg)
.
If other options are desired, use coral_config_command()
instead.
Returns a non-negative integer for success, -1 for failure.
int coral_config_command(const char *command);
Processes a config command. This function should be used instead of
coral_config_options()
or coral_config_arguments()
if you need to accept your own options in addition to CoralReef options,
or you want to accept CoralReef commands from inputs other than the command line.
Returns 0 for success, -1 for failure.
int coral_config_file(const char *filename);
Process CoralReef commands in file filename.
This is not usually needed if coral_config_arguments()
,
coral_config_options()
, or coral_config_command()
is used.
int coral_usage(const char *appname,
const char *argmsg,
...);
Prints a message describing the command line syntax of a CoralReef application
named appname.
If argmsg is not NULL
,
it is used as a printf-style format for the arguments that follow,
and the formatted result is appended to the syntax line.
This is followed by descriptions of the CoralReef (-C) command line options.
Some example values for argmsg:
NULL
"[<argument>]"
"[-f] [-b<N>] <source>..."
If only CoralReef options and sourcename arguments are needed, this simple code will do:
coral_set_api(CORAL_API_PKT); if (coral_config_arguments(argc, argv) < 0) exit(-1);If other options are desired, you must parse the options and arguments yourself, like this:
int opt, foo_flag = 0, bar = 42; extern char *optarg; extern int optind; coral_set_api(CORAL_API_PKT); while ((opt = getopt(argc, argv, "C:fb:")) != -1) { switch (opt) { case 'C': if (coral_config_command(optarg) < 0) exit(-1); break; case 'f': foo_flag = 1; break; case 'b': bar = atoi(optarg); break; default: coral_usage(argv[0], "[-f] [-b<N>] <source>...\n" "-f foo flag\n" "-b<n> bar value (default %d)\n", bar); exit(-1); } } while (optind < argc) { if (!coral_new_source(argv[optind])) exit(-1); optind++; }If a bad option is given, this code will print a message like this to stderr, followed by descriptions of the CoralReef commands that are allowed for the configured API:
Usage: app [-C <coral_command>]... [-f] [-b<N>] <source>...
The following functions provide a way for the programmer to set global
configuration values, including default values for the configuration of
sources that have not yet been defined.
The coral_set
functions can be called
before the coral_config
functions to set default
values that can be overridden on the command line or config file, and will
be displayed in the coral_usage
message.
If the integer configuration values are set to a negative value,
they will not be displayed in the coral_usage
message.
The coral_set
functions can also be called
after the coral_config
functions
so their values can't be overridden.
They must not be called after sources are opened.
The coral_set
functions return 0 if successful, or -1 for failure;
the coral_get
functions return the value of the requested datum.
void coral_config_defaults(void);
Resets libcoral configuration to its default state. Should not be called while sources are open. The affected configuration values are: max_sources, options, duration, interval, dropinterval, mintime, maxtime, errfile, iomode, comment, gzip level, pcap filter, api, max_blks, max_cells, max_pkts, skip_pkts, bandwidth, physical protocol, datalink protocol, firmware.
int coral_set_api(int api);
The api parameter to coral_set_api()
must be
CORAL_API_BLOCK
,
CORAL_API_CELL
, or
CORAL_API_PKT
,
optionally bitwise ORed with
CORAL_API_WRITE
.
It initializes libcoral for use with the corresponding APIs,
and should be called before any coral config, reading, or writing function.
Setting the APIs enables command line and configuration file options and functions that are specific to those APIs. Libcoral will generate an error if any disallowed option or function is attempted.
The api parameter should contain exactly one of the following constants:
API | allowed configuration commands | allowed functions |
CORAL_API_BLOCK
|
blocks
| |
CORAL_API_CELL
|
cells
blocks
deny
| |
CORAL_API_PKT
|
packets
filter
deny
|
coral_add_pcap_filter()
|
Commands and functions not listed under any API are valid for all APIs.
The api parameter may optionally be bitwise-ORed with this constant, if coral_write or a rotating output file will be used:
API | allowed configuration commands | allowed functions |
CORAL_API_WRITE
|
gzip
|
coral_set_gzip()
|
Example: coral_set_api(CORAL_API_PKT | CORAL_API_WRITE);
int coral_set_max_sources(int n);
int coral_get_max_sources(void);
coral_set_max_sources()
sets the maximum number of allowed Coral
sources to n. It should be called before
coral_config_arguments()
,
coral_config_options()
,
coral_config_command()
, and
coral_new_source()
to restrict them.
It returns 0 if successful,
or -1 if n is negative or greater than 16.
coral_get_max_sources()
returns the maximum number of allowed Coral
sources.
The default max_sources value is 16.
int coral_set_options(int off,
int on);
int coral_get_options(void);
coral_set_options()
disables the options in the bitmask
off and enables the options in the bitmask on.
coral_get_options()
returns a bitmask of currently enabled options.
The options are:
CORAL_OPT_SORT_TIME
(default: off)
coral_read_cell_all()
and coral_read_pkt()
read in timestamp order.
For this option to make sense, one of the following must be true:
all interfaces have start epochs and were started at the same time, or
all interfaces have unix epochs, or
the CORAL_OPT_NORMALIZE_TIME
option is on.
If none of these conditions is true, libcoral will automatically enable the
CORAL_OPT_NORMALIZE_TIME
option.
If your application requires time sorting, set this option before
the command-line coral_config
functions so
"sort"
will not appear in the coral_usage message.
CORAL_OPT_ALIGNINT
(default: off)
CORAL_OPT_PARTIAL_PKT
(default: on)
coral_read_pkt()
and coral_read_pkts()
to handle partial packets.
CORAL_OPT_FATM_RAW_TIME
(default: off)
CORAL_OPT_POINT_RAW_TIME
(default: off)
CORAL_OPT_RAW_TIME
(CORAL_OPT_FATM_RAW_TIME
| CORAL_OPT_POINT_RAW_TIME
)
.
CORAL_OPT_NORMALIZE_TIME
(default: on)
CORAL_OPT_SORT_TIME
)
with different default epochs.
But normalizing may introduce inaccuracy if
the interfaces' hosts' CPU clocks are inaccurate,
and may introduce additional processing overhead.
The default epochs for the various types of interfaces are:
coral_start_all
());
coral_start_all
());
CORAL_OPT_NO_FILTER
(default: off)
CORAL_OPT_IP_CKSUM
(default: off)
coral_fmt_get_payload()
to print and verify IP checksums.
CORAL_OPT_IP_EXTHDR
(default: off)
coral_get_payload()
to not skip IP extension headers.
CORAL_OPT_IGNORE_TIME_ERR
(default: off)
CORAL_OPT_NO_AUTOROTATE_ERRFILE
(default: off)
int coral_set_iomode(unsigned off,
unsigned on,
int first,
int fixed);
This function sets the default I/O mode of all subsequently defined sources.
(To set the I/O mode of sources that have already been defined, use
coral_source_set_iomode()
.)
The arguments to this function are:
coral_config
functions, in applications
with a non-configurable iomode).
The I/O mode flags are:
flag | equivalent CLI iomode | description |
CORAL_TX | tx | allow transmitting (not implemented) |
CORAL_RX | rx | allow receiving |
CORAL_RX_IDLE | idle | read all cells, including ATM idle cells |
CORAL_RX_OAM | ctrl | read ATM OAM/RM cells |
CORAL_RX_LAST | last | read last cell of each ATM AAL5 user PDU (packet) |
CORAL_RX_USER_ALL | user | read all bytes of each packet or frame |
CORAL_RX_ECHO | echo | retransmit received cells on devices which support it (always enabled on POINT cards) |
CORAL_RX_UNKNOWN | for traces, read whatever cells are in the trace file; for devices, use default mode (i.e., rx first=48). Setting this flag clears all other settings. |
This function returns 0 for success, -1 for failure. It only affects sources that are created after it is called.
Setting first overrides a previously set
CORAL_RX_USER_ALL
flag, and
setting the CORAL_RX_USER_ALL
flag
overrides a previously set first value.
Attempting to set both at once has undefined results.
The default I/O mode is CORAL_RX, and first==48. Currently, an attempt to explicitly use an I/O mode to read a trace that does not match the I/O mode used to record the trace will generate a warning, but all the data in the trace will still be read. In a future release, the read functions may filter trace files according to the I/O mode (or generate an error if that is not possible).
For a summary of the iomode options supported by the various interface types, see the command usage document.
const coral_io_mode_t *coral_get_iomode(void);
Return the default iomode
as set by coral_set_iomode()
or command line options.
int coral_set_errfile(FILE *file);
int coral_set_errfilename(const char *filename);
FILE *coral_get_errfile(void);
coral_set_errfile()
and coral_set_errfilename()
set
the destination for future libcoral error and warning messages.
file is an already opened stdio stream pointer, and
filename is the name of a file that will be opened by libcoral.
Any previously set error file will be closed only if it was set by name other
than "-"
(i.e., by coral_set_errfilename()
,
but not by coral_set_errfile()
).
If file or filename is NULL
,
stderr will be used.
If filename is "-"
, stdout will be used.
coral_get_errfile()
returns the current message destination.
The default message destination is stderr.
If the name of the error file contains "%", the error file will be
rotatable and the actual filename will be
generated as described in coral_rf_open.
Unlike normal rotfiles,
a rotating error file is always writable
by coral_diag and libcoral;
it does not need to be started.
A rotatable error file will rotate automatically at the beginning of each
interval of coral_read_pkt or coral_read_pkts, unless then
CORAL_OPT_NO_AUTOROTATE_ERRFILE
option is set.
In any case, coral_rotate_errfile
can be called to rotate
the error file explicitly.
If rotation fails, the error file resets to stderr.
int coral_set_verbosity(int verbosity);
int coral_get_verbosity(void);
Set or get the verbosity level of libcoral and coral_diag()
.
If verbosity==0, only errors are printed;
if verbosity==1 errors and warnings are printed.
Meanings for values greater than 1 may be assigned by the programmer
for use with coral_diag()
.
The default verbosity is 1.
To completely disable coral messages, set the verbosity to -1.
int coral_set_max_pkts(uint64_t n);
int coral_set_max_cells(uint64_t n);
int coral_set_max_blks(uint64_t n);
uint64_t coral_get_max_pkts(void);
uint64_t coral_get_max_cells(void);
uint64_t coral_get_max_blks(void);
These functions get or set the maximum record count that will be read by the reading APIs. When the limit is reached, reading functions will indicate EOF. If set to zero, there is no limit. All three counts are zero by default.
count | affected APIs |
max_pkts | packet |
max_cells | cell |
max_blks | block and cell |
int coral_set_skip_pkts(uint64_t n);
uint64_t coral_get_skip_pkts(void);
Get or set the number of packets that will be discarded by the packet reading API.
int coral_set_comment(const char *comment);
const char *coral_get_comment(void);
Set or get the default comment that will be written in the file header by the
coral_write
functions. The default comment may
be overridden by
coral_write_set_comment()
.
int coral_set_duration(long duration);
long coral_get_duration(void);
Set or get the duration value.
If the duration value is greater than 0, it determines how long libcoral will read from sources after they are started; after the duration has expired, the reading function will indicate EOF. Libcoral uses both real time and cell timestamps to test duration, so it will work with tracefiles and devices receiving live traffic.
With the default duration of -1, the coral_config
functions
will not allow duration to be set.
To have your application not use duration by default, but still let the
user override it, set it to 0
before calling the coral_config
functions.
Before version 3.3.0, libcoral did not test duration when reading; the programmer was expected to handle it himself. Now, the programmer should do nothing other than enable it, and let libcoral's reading functions handle the duration.
Libcoral does not use SIGALRM to implement duration.
int coral_set_interval(const struct timeval *interval);
int coral_get_interval(struct timeval *interval);
Set or get the interval value.
If the interval has not yet been set, coral_get_interval()
returns -1 and fills in *interval with { -1, -1 }; otherwise, it
returns 0 and fills in *interval with the nonnegative interval value.
The interval value is never automatically used by libcoral; it just provides a
convenient and consistent way to let the user set an interval on the command
line or in a config file. The programmer may use the interval by passing
the result of coral_get_interval()
in as a parameter to
coral_read_pkt_init()
or
coral_read_cell_i()
.
Libcoral uses cell/packet timestamps, not real time, to test for intervals.
Therefore the intervals it
reports will be correct for both tracefiles and devices, although the act
of reporting may be delayed because of internal buffering.
With the default interval of -1, the coral_config
functions
will not allow interval to be set.
To have your application not use interval by default, but still let the
user override it, set it to 0.0
before calling the coral_config
functions.
Libcoral does not use SIGALRM to implement interval.
See also: CORAL_OPT_ALIGNINT
.
int coral_set_dropinterval(const struct timeval *dropinterval);
int coral_get_dropinterval(struct timeval *dropinterval);
Set or get the dropinterval value.
The default dropinterval value is { 0, 0 }.
If the dropinterval has been set to a negative value,
coral_get_dropinterval()
returns -1 and fills in *interval with { -1, -1 }; otherwise, it
returns 0 and fills in *interval with the nonnegative interval value.
A positive value for dropinterval is used as the period with which
coral_read_pkt()
will report packet drops on live pcap interfaces
to the error file.
Note that dropinterval uses setitimer() and SIGALRM. If that would interfere
with your application, you may prevent the user from setting dropinterval
on the command line by setting it to a negative value
before calling the coral_config
functions.
The dropinterval is independent of the normal
interval and CORAL_OPT_ALIGNINT
.
int coral_set_mintime(const struct timeval *t);
int coral_get_mintime(struct timeval *t);
int coral_set_maxtime(const struct timeval *t);
int coral_get_maxtime(struct timeval *t);
Set or get the mintime or maxtime value. If the desired value has not yet been set, the get functions return -1 and fill in *t with { -1, -1 }; otherwise, they return 0 and fill in *t with the nonnegative interval value.
Libcoral will discard all packets whose timestamp is less than mintime or greater than maxtime. Libcoral uses cell/packet timestamps, not real time, to test these time bounds, so the packets it discards will be correct for both tracefiles and devices.
With the default duration of -1, the coral_config
functions
will not allow interval to be set.
To have your application not use time bounds by default, but still let the
user override them, set duration to 0
before calling the coral_config
functions.
int coral_set_gzip(const str *mode);
If mode is NULL
, coral_write_open()
will not gzip files
unless they end in ".gz".
If mode is "", coral_write_open()
will gzip files with the
default parameters (compression level 1).
If mode is a non-empty string,
coral_write_open()
will append it to the "wb" mode when calling
gzopen()
; see the zlib documentation for details.
coral_source_t *coral_new_source(const char *sourcename);
Create a new coral source
from sourcename.
Sources are described in the
Command usage document.
Returns source pointer if successful, or NULL
for failure.
This function is useful for creating a source directly from the program
(instead of through command line and config file with the
coral_config
functions).
coral_source_t *coral_new_fdsource(int fd,
const char *sourcename);
Like coral_new_source, except that it uses the already-open
file descriptor fd
instead of a filename.
If sourcename is not NULL
, coral_open()
will examine it for a prefix or suffix
to determine how to interpret the data read from fd;
otherwise, coral_open()
will assume data from fd contains a
CoralReef (crl) trace.
This function is useful for creating a source directly from a
file descriptor in the program;
for example, a socket connected to another process that used
coral_write_fdopen()
.
Mixing CoralReef operations with other operations on descriptor fd may have unpredictable effects.
int coral_source_set_iomode(coral_source_t *src,
unsigned off,
unsigned on,
int first);
int coral_source_set_iomode_all(unsigned off,
unsigned on,
int first);
These functions modify the I/O mode of the indicated already defined sources. The off, on, and first arguments are identical to those of coral_set_iomode(). These functions return 0 for success, -1 for failure.
To set the default I/O mode of sources that have not yet been defined, use coral_set_iomode().
const coral_io_mode_t *coral_source_get_iomode(const coral_source_t *src);
const coral_io_mode_t *coral_iface_get_iomode(const coral_iface_t *iface);
Return the iomode of src or iface, respectively. Note that for live interfaces, it is the iomode of the interface that determines how data is read; the iomode of the source is just a default that an interface may inherit. For file interfaces, the iomode of the interface is that of the original device, and the iomode of the source has little meaning.
int coral_format_iomode(char *buffer,
const coral_io_mode_t *iomode);
Prints a human-readable representation of iomode into buffer.
buffer must be at least CORAL_FORMAT_IOMODE_LEN
bytes long.
Returns the length of the formatted string.
int coral_source_set_firmware(coral_source_t *src,
const char *firmware);
int coral_source_set_firmware_all(const char *firmware);
Set the location of the firmware file of source src, or of all sources. The firmware will be loaded when the source is opened. Returns 0 for success, -1 for failure.
/proc/dag
will report the device is "Busy");
the card must be re-initialized before CoralReef can read from it again.
int coral_open(coral_source_t *src);
int coral_open_all(void);
Open the indicated coral sources that have been created by
coral_config_arguments()
, coral_config_options()
,
coral_config_command()
, and coral_new_source()
,
but do not start them.
If successful, these functions return the number of interfaces opened.
If unsuccessful, these functions return -1 and close
the source which failed.
Note that a single tracefile source may contain multiple interfaces.
int coral_start(coral_source_t *src);
int coral_start_all(void);
Start capture on interface(s) of the indicated coral sources which have been
opened with coral_open()
or coral_open_all()
.
Additionally, coral_start_all()
resets the clocks of all
open interfaces that allow it, to synchronize them.
A source can not be read until it is started with one of these functions.
(Prior to version 3.3, it was not strictly necessary to start tracefile
sources.)
int coral_stop_all(void);
int coral_stop(coral_source_t *src);
Stop capturing on all interfaces of the indicated device sources. Returns 0 for success, -1 for failure. After a source is stopped, it may still contain buffered data, which can be read until the reading function returns an EOF indication. These functions are not safe to call asynchronously (e.g., from a signal handler).
See also: coral_pkt_done.
int coral_close_all(void);
int coral_close(coral_source_t *src);
Close all interfaces of the indicated sources, after flushing any partially filled blocks. Returns 0 for success, -1 for failure.
The packet reading functions may be used with any CoralReef interface that has
been started.
All time is measured against packet
timestamps, so it works even for trace files that aren't in real time.
If pcap filtering is enabled,
packets that do not match the filter are discarded.
If anonymization is enabled,
IP addresses in packets will be anonymized,
and non-IP packets are truncated.
See crl_print_pkt.c
for a good example of using the packet API.
Note that the data in packets returned by the packet API is not guaranteed
to have any particular alignment.
The functions crl_nptohl()
and
crl_nptohs()
can be used to convert data to
host byte order and handle the alignment at the same time.
int coral_read_pkt_init(coral_source_t *src,
coral_iface_t *iface,
struct timeval *interval);
Prepare to read packets from an open src or iface with
coral_read_pkt()
.
If iface is not NULL
,
packets will be read from iface;
otherwise, if src is not NULL
,
packets will be read from all interfaces of src;
otherwise, packets will be read from all interfaces of all open sources.
There is no restriction on reading multiple pcap sources or mixing pcap and
OCx sources, as there was prior to version 3.4.
If iface belongs to a source with multiple interfaces, data
from the other interfaces of that source will be discarded.
Packets can be read from only one set of sources at a time;
calling coral_read_pkt_init()
invalidates any sources that were
previously initialized for packet reading.
Interval is the amount of time coral_read_pkt()
will wait between returning statistical information (measured against packet
timestamps).
Because coral_read_pkt()
must be able to compare timestamps,
coral_read_pkt_init()
will automatically enable the
CORAL_OPT_NORMALIZE_TIME
option if necessary.
coral_read_pkt_init()
returns 0 if successful, or -1 if an
error occurs.
coral_iface_t *coral_read_pkt(coral_pkt_result_t *pkt_result,
coral_interval_result_t *interval_result);
Read a packet from one of the interfaces which have been
initialized with coral_read_pkt_init()
.
If a packet filter has been set, only
packets that match the filter will be read.
Packets read are sorted by time only if the CORAL_OPT_SORT_TIME
option
was set when coral_read_pkt_init()
is called
(prior to version 3.6, packets were always sorted by time,
regardless of the setting of the CORAL_OPT_SORT_TIME
option).
Even if sorting is disabled, packets will be returned in the correct interval,
and no packets will be returned after the duration has expired.
If the CORAL_OPT_PARTIAL_PKT
option is turned off, only complete packets will be read
(but truncated packets are always counted by the truncated field of
coral_pkt_stats_t).
pkt_result and interval_result are
pointers to structures (allocated by the programmer)
that will be filled in by the call.
For success, coral_read_pkt()
returns a pointer to
the interface which was read,
and the contents of the structures indicate what happened:
if (pkt_result->packet != NULL) {
pkt_result
.pkt_result->packet
will point to a
coral_pkt_buffer_t
containing the link layer (LLC/SNAP, ethernet, etc) PDU.
On ATM interfaces,
pkt_result->header
will point to a
coral_pkt_buffer_t
containing the first 4 bytes of the ATM header of the last captured cell
of the packet (in network byte order);
pkt_result->trailer
will point to a
coral_pkt_buffer_t
containing the AAL5 trailer (in network byte order), if available; and
pkt_result->subiface
will contain the ATM vpvc
(in host byte order) from which the packet was read.
On IEEE 802.3/Ethernet interfaces carrying IEEE 802.1Q VLAN traffic,
pkt_result->subiface
will be the VLAN ID.
On other types of interfaces, pkt_result->header
and pkt_result->trailer
will be NULL
,
and pkt_result->subiface
will be 0.
} else if (interval_result->stats == NULL) {
interval_result->begin
.
(interval_result->end
is not valid.)
} else {
interval_result->begin
and
ending at interval_result->end
has ended.
Statistics for the interval are contained in
interval_result->stats
.
All packets read after this point will have timestamps greater than
interval_result->end
, even if
the CORAL_OPT_SORT_TIME
option is not enabled.
}
If the interval specified in coral_read_pkt_init()
was
NULL
or 0,
interval_result may be NULL
,
and coral_read_pkt()
will never return with
pkt_result->packet == NULL
.
The beginning of an interval is not aligned to a multiple of
the interval size.
When reading from a live interface, internal buffering may cause reporting of
the end of the interval to be delayed, but the data reported will cover exactly
the requested interval.
(In versions 3.2.x, the reported interval included "quiet" (trafficless) time
after the end of the requested time.
In versions 3.1 and earlier, the data reported
included packets past the end of the interval that fell in the same internal
buffer as the end of the interval.) Interval comparisons are made against
packet timestamps, not a real clock, so the same results will be produced by
reading a live interface or reading a trace taken on that interface in the
same period.
The protocol of pkt_result->packet
is determined by the interface type.
For ATM interfaces, the protocol is determined by the virtual channel and
proto
configuration rules as by coral_proto_rule()
.
Note that if the configuration is incorrect, the packet buffer will
not make sense.
For TSH interfaces, the protocol for a valid packet is always
CORAL_NETPROTO_IPv4
,
and IP options are always zero; the protocol of an invalid packet is
CORAL_PROTO_UNKNOWN
.
Packets read from raw IP sources (i.e., pcap DLT_RAW) will have their
protocol set to CORAL_NETPROTO_IPv4
or CORAL_NETPROTO_IPv6
if they contain at least 1 byte of data; otherwise, they will have
protocol CORAL_NETPROTO_RAW_IP
.
If coral_cell_block_hook points to a programmer-defined function, it will be called when a new block of ATM cells is read.
To indicate EOF, a stopped device, or
expired duration,
coral_read_pkt()
returns
NULL
with errno == 0
.
For an error, coral_read_pkt()
returns NULL
with
errno
set to indicate the type of error.
(Certain types of errors that were reported as EOF in versions prior 3.5
are now correctly reported as errors.)
If coral_get_verbosity() >= 1, then
at the end of every interval,
if there were any packet errors
(nonzero fields in interval_result->stats
)
during the interval,
coral_read_pkt()
prints warnings to the error file.
If intervals were not used, the warnings are printed only at EOF,
covering the entire duration.
Typical packet reading code looks like this:
{ coral_iface_t *iface; coral_pkt_result_t pkt_result; coral_interval_result_t interval_result; struct timeval interval = {300,0}; ... coral_read_pkt_init(NULL, NULL, &interval); while (1) { iface = coral_read_pkt(&pkt_result, &interval_result); if (!iface) { /* error */ break; } if (pkt_result.packet) { /* got packet */ ... } else if (!interval_result.stats) { /* beginning of interval */ ... } else { /* end of interval */ ... } } }
int coral_read_pkts(coral_source_t *src,
coral_iface_t *iface,
coral_pkt_handler pkthandler,
coral_pre_interval_handler preinthandler,
coral_post_interval_handler postinthandler,
struct timeval *interval,
void *mydata);
Reads packets from one or more interfaces, and calls a handler function
for each packet read and for the beginning and end of each interval.
Src, iface, and interval
are interpreted as in coral_read_pkt_init()
.
coral_read_pkts()
repeatedly reads link level packets
(using coral_read_pkt())
until (coral_pkt_done != 0)
or EOF is reached on all interfaces.
Pkthandler is a pointer to a function that will be called for each packet received.
Preinthandler and postinthandler are pointers to
functions that will be called before and after each interval of
*interval seconds in which packets were received.
Preinthandler and postinthandler are not called if they
are NULL
, interval is NULL
,
or *interval is less than or equal to 0.0.
Mydata will be passed as a parameter to the handler functions, but otherwise ignored; the programmer may use it as needed.
Postinthandler may set coral_pkt_done
to nonzero to
make coral_read_pkts()
stop looping and return.
coral_read_pkts()
returns 0 if it reaches EOF with no errors;
or -1 if there is an error, with errno set to indicate the type of error.
(Certain types of errors that were reported as EOF in versions prior to 3.5
are now correctly reported as errors.)
typedef void (*coral_pkt_handler)(coral_iface_t *iface,
const coral_timestamp_t *timestamp,
void *mydata,
coral_pkt_buffer_t *packet,
coral_pkt_buffer_t *header,
coral_pkt_buffer_t *trailer);
coral_pkt_handler
is the type of the function called each time
coral_read_pkts()
reads a packet.
Parameters:
coral_read_pkts()
.
NULL
.
Currently, this is only used for the ATM header of the last received
cell in the packet; the ATM header will be in network byte order
(in version 3.1, this was in host byte order).
NULL
.
Currently, this is only used for the ATM AAL5 trailer.
typedef void (*coral_pre_interval_handler)(coral_iface_t *iface,
const struct timeval *begin,
void *mydata);
typedef void (*coral_post_interval_handler)(coral_iface_t *iface,
const struct timeval *begin,
const struct timeval *end,
void *mydata,
const coral_pkt_stats_t *stats);
coral_pre_interval_handler
and coral_post_interval_handler
are the types of the functions called before and after (respectively) each
interval of coral_read_pkts()
.
Parameters:
coral_read_pkts()
const coral_pkt_stats_t *coral_get_iface_stats(coral_iface_t *iface);
Returns a pointer to the coral_pkt_stats_t structure for iface for the most recent interval.
extern volatile int coral_pkt_done;
This can be set to a non-zero value at any time (e.g., in postblkhandler or in a signal handler) to force either packet reading function to act like it has detected EOF the next time it is called, on both device and trace file sources.
See also: coral_stop_all()
.
extern int (*coral_pkt_atm_hook)(const coral_iface_t *iface,
const coral_pkt_buffer_t *packet,
const coral_atm_cell_t *cell);
If coral_pkt_atm_hook
is not NULL
, the function
to which it points is called each time the first cell of an AAL5 PDU is seen by
coral_read_pkt()
or
coral_read_pkts()
on an ATM interface.
If this function returns 0, the packet reader function will skip
the packet to which the cell belongs;
if it returns nonzero, or the function pointer is NULL
,
the packet reader function will process the packet normally.
The coral_pkt_atm_hook
test is done before any reassembly is
performed, so it is more efficient to discard packets in
coral_pkt_atm_hook
than after
coral_read_pkt()
returns or in the
coral_pkt_handler
of
coral_read_pkts()
.
The parameters are:
coral_pkt_buffer_t
parameter (e.g.,
coral_get_payload()
).
The default value of coral_pkt_atm_hook
is NULL
.
See also: coral_add_pcap_filter() and coral_pcap_setfilter().
int coral_get_payload(const coral_pkt_buffer_t *src,
coral_pkt_buffer_t *dst);
src is a pointer to a
coral_pkt_buffer_t
containing a datagram or packet
(e.g., packet_result->packet from coral_read_pkt())
with src->caplen > 0
.
coral_get_payload()
skips past the lower level (outer) protocol
encapsulation in src and fills in dst with information
about the payload of src
(see coral_pkt_buffer_t).
If coral_get_payload()
understands the src protocol
but does not recognize the protocol of the payload,
dst->protocol
will contain
CORAL_PROTO_UNKNOWN
or some other undefined value.
coral_get_payload()
returns 0 if it successfully parsed
the src protocol information, or one of the following negative
error codes:
A return value of CORAL_ELENGTH indicates that some desired part of the
packet was truncated, but dst will still contain as much information
as was available.
For example, if src contained an IPv4 packet truncated between
the length field and the protocol field, then
dst->buf
will point to the beginning of the next layer,
and dst->totlen
will be the correct length of the next layer,
but dst->protocol
will be CORAL_PROTO_UNKNOWN
.
For all other error return values, the contents of dst are undefined.
The recognized protocols are listed in the
Protocols section of the
Command Usage document.
Protocol identifiers are formed by concatenating
"CORAL_
", the prefix, and the name;
e.g., CORAL_DLT_ETHER
.
By default, the IPv6 extension headers
HOPOPTS, ROUTING, FRAGMENT, and DSTOPTS are skipped;
but if the CORAL_OPT_IP_EXTHDR
option is on,
they are treated as encapsulated protocols.
The extension headers AH and ESP are never skipped.
So, for example, say you have an Ethernet frame containing an IPv6 packet
with a Routing header, Fragment header, and UDP datagram.
If you call coral_get_payload()
with that packet as src,
and then repeatedly with the dst of the previous call as the src
of the next,
with CORAL_OPT_IP_EXTHDR
off,
the value of dst->protocol
after each successive call would be
CORAL_NETPROTO_IPv6
,
CORAL_IPPROTO_UDP
, and
CORAL_PROTO_UNKNOWN
,
respectively.
But the same sequence with CORAL_OPT_IP_EXTHDR
on
would result in
CORAL_NETPROTO_IPv6
,
CORAL_IPPROTO_ROUTING
,
CORAL_IPPROTO_FRAGMENT
,
CORAL_IPPROTO_UDP
, and
CORAL_PROTO_UNKNOWN
.
(In versions 3.5.0 and 3.5.1, this function behaved as if CORAL_OPT_IP_EXTHDR
were always on.)
Note: TSH files contain IPv4 packet headers only, and when CoralReef reads an IPv4 packet from a TSH file it fills the missing IP options (if any) with zeros to create a syntactically valid substring of an IP packet.
int coral_fmt_get_payload(const coral_pkt_buffer_t *src,
coral_pkt_buffer_t *dst,
char *buf,
int len);
coral_fmt_get_payload()
is like
coral_get_payload()
, except that it also writes
up to len characters (including a terminating null character) of
human-readable information about the lower level protocol into buf.
Returns a nonnegative number if successful,
or -1 for any of the following errors:
vsnprintf()
is not available on your system
and buf is not NULL
;
or any of the errors listed in the documentation for
coral_get_payload().
A return value of CORAL_ELENGTH indicates that some desired part of the
packet was truncated, but dst and buf will still contain as much
information as was available.
For all other error return values, the contents of dst and buf
are undefined.
The information written into buf attempts to cover all relevant information
about the protocol. Irrelevant information is omitted for brevity (for
example: for TCP, the urgent pointer and acknowledgment number are printed
only if the corresponding flags are set;
for IPv4, type-of-service is printed only if it is nonzero,
and the fragment offset is printed only if the packet is a fragment).
The IP checksum will be printed and verified only if the
CORAL_OPT_IP_CKSUM
option is set.
int coral_get_payload_by_proto(const coral_pkt_buffer_t *src,
coral_pkt_buffer_t *dst,
coral_protocol_t proto);
int coral_get_payload_by_layer(const coral_pkt_buffer_t *src,
coral_pkt_buffer_t *dst,
int layer);
These functions search for the outermost packet in src whose protocol is proto or protocol layer is layer, and copy that packet's information to dst. The copied packet will be src itself if its protocol matches the criterion; otherwise these functions repeatedly call coral_get_payload() to find encapsulated packets. These functions return 0 if successful, or -1 if the proto or layer is not found, or for any of the errors listed in the documentation for coral_get_payload().
int coral_pkt_truncate(const coral_pkt_buffer_t *pkt,
int layer,
int unknown,
int payload);
Effectively truncates packet by protocol: keeps the headers of the first layer layers plus payload bytes of layer layer payload. It does this by reseting pkt->caplen to the lowest of:
CORAL_PROTO_UNKNOWN
Returns the same values as coral_get_payload().
const char *coral_get_net_pkt(const coral_pkt_buffer_t *buffer,
int *protocol);
Obsolete. See coral_get_payload()
int coral_field_fits(p,
FIELDNAME,
caplen);
Returns nonzero iff p->FIELDNAME fits within the first caplen bytes of the structure pointed to by p. This is useful when you have read a packet that may be truncated and want to know if a specific header field is valid. The type of p must be a pointer to a structure that has FIELDNAME as a member, and FIELDNAME must not be a bitfield (e.g., ip_hl of struct ip).
In the following example, netpkt is a coral_pkt_buffer_t that has already been filled in by one of the coral_get_payload functions.
if (netpkt.protocol == CORAL_NETPROTO_IP) { struct ip *ip = netpkt.buf; if (!coral_field_fits(ip, ip_p, netpkt.caplen)) { coral_printf("packet too short\n"); } else { switch (ip->ip_p) { case IPPROTO_TCP: ... case IPPROTO_UDP: ... } } }
If libcoral was compiled with libpcap, these functions can be used to set pcap filter expressions. Pcap filters can be used with any type of interface, not just BPF devices. The filter will be executed when it is most efficient: in the kernel if the interface is a BPF device, or before AAL5 reassembly (if possible) if the interface is an ATM Coral device or file. The packet reading functions will return only packets which match the filter.
int coral_add_pcap_filter(const char *expr);
int coral_add_pcap_prefilter(const char *expr);
int coral_add_pcap_ipfilter(const char *expr);
If expr is not NULL
, coral_add_pcap_filter()
sets expr as a global pcap filter expression.
If a filter expression was already set (either by this function or by
coral_config "filter" commands),
the old and new expressions are joined as
"(old_expr) and (expr)
".
The expression will be compiled and set on every source that is subsequently
opened; it has no effect on sources that are already open.
If expr is NULL
,
coral_add_pcap_filter()
clears
any previously set global pcap filter expression.
These functions will not work until coral_set_api(CORAL_API_PKT)
is called.
This function returns 0 if successful,
or -1 with errno set if there is an error.
coral_add_pcap_prefilter()
is similar to
coral_add_pcap_filter()
,
except it sets a "prefilter", which is used only on ATM interfaces,
on the first ATM cell, before AAL5 reassembly. A prefilter
can be used to avoid unnecessary reassembly, but only if the first ATM
cell contains enough information to apply the filter. It is up to the
user to make sure the prefilter does not need information that does
not fit in the first cell.
coral_add_pcap_ipfilter()
is similar to
coral_add_pcap_filter()
,
except that for each packet CoralReef first skips past layer 2 to find an
IP packet. If no IP packet is found, the packet is discarded; otherwise, the
filter is tested starting at the IP header.
This is useful when packets contain IP encapsulated in some layer 2
protocol that pcap filters can not parse, but CoralReef can,
such as MPLS.
See also the section on -Cfilter in the command usage document.
const char *coral_get_pcap_filter(void);
const char *coral_get_pcap_prefilter(void);
const char *coral_get_pcap_ipfilter(void);
Returns the text of the global pcap filter expression
previously set by
coral_add_pcap_filter() or coral_add_pcap_prefilter()
and/or by coral_config
"filter" or "prefilter"
commands.
Returns NULL
if no filter expression has been set.
#include <pcap.h>
int coral_pcap_compile(coral_iface_t *iface,
struct bpf_program *fp,
char *str,
int optimize,
uint32_t netmask);
int coral_pcap_setfilter(coral_iface_t *iface,
struct bpf_program *fp);
int coral_pcap_setprefilter(coral_iface_t *iface,
struct bpf_program *fp);
If you need finer control over pcap filtering than coral_add_pcap_filter() and coral_add_pcap_prefilter() provide, you can use these functions. These allow you to recompile and reset filters at any time (even on interfaces that are already open), and to assign different filters to different interfaces.
These functions are the same as pcap_compile()
and
pcap_setfilter()
, respectively, except that they apply to a
coral_iface_t
instead of a
pcap_t
. They are used to compile a tcpdump expression to a
BPF program and install
it onto a Coral interface. Note that *fp
must remain
in valid memory until iface is closed or a new BPF program is
installed on iface.
To avoid confusion when using these functions, you should set the
CORAL_OPT_NO_FILTER
option
before calling the coral_config functions
to prevent the user from specifying a useless "filter" command.
Alternatively, you could allow the user to use "filter" commands,
use coral_get_pcap_filter()
to get it so you can combine it with yours, and
coral_add_pcap_filter(NULL)
to clear the global expression so it won't be applied by
coral_open().
See the pcap and tcpdump documentation for more information.
coral_anon_t *coral_get_anonymizer();
Return a pointer to a copy of the global coral_anon_t object created by the "anonymize" configuration command, or NULL if "anonymize" was not used.
int coral_set_anonymizer(coral_anon_t *anon);
Set a global coral_anon_t object to be used by the packet API. If anon is NULL, anonymization in the packet API will be disabled. Anonymization is applied after pcap filtering.
In applications that do a lot of aggregation and need to output anonymized results, it can be more efficient to anonymize after aggregation. To do this, use coral_get_anonymizer() to get the coral_anon_t that was configured on the command line, use coral_set_anonymizer(NULL) to disable automatic anonymization, and call coral_anonymize() or coral_pkt_anonymize() on each address or packet in the aggregated results before outputting them.
void coral_anonymize_ip4(coral_anon_t *anon,
void *newaddr,
const void *oldaddr);
void coral_anonymize_ip6(coral_anon_t *anon,
void *newaddr,
const void *oldaddr);
Writes an anonymized copy of IPv4 or IPv6 address oldaddr into newaddr. All addresses are in network byte order. anon must be a pointer to a coral_anon_t object returned by coral_get_anonymizer().
Bug: these functions do not know if addr is a source or a
destination address, so they anonymize unconditionally,
ignoring the src
and dst
parameters of the "anonymize" configuration command.
Example:
struct in_addr oldaddr, newaddr; coral_anon_t *anon = coral_get_anonymizer(); ... coral_anonymize_ip4(anon, &newaddr, &oldaddr);
uint32_t coral_anonymize(coral_anon_t *anon,
uint32_t addr);
Returns an anonymized copy of IPv4 address addr. All addresses are in host byte order. See also coral_anonymize_ip4.
int coral_pkt_anonymize(coral_pkt_buffer_t *pkt);
Anonymizes source and destination addresses within IPv4 and IPv6 headers of
the packet pointed to by pkt,
using the global coral_anon_t set by
the "anonymize" configuration command.
If the packet contains an IP packet which directly or indirectly
encapsulates other IP packets using any protocol that libcoral understands
(e.g., IPIP, or the original IP packet inside an ICMP error message),
addresses in the encapsulated IP headers are also anonymized.
If an address is truncated due to insufficient pkt->caplen
,
the partial address is still anonymized.
IP, TCP, and UDP checksums are incrementally recalculated to reflect the
changed addresses (this is new in version 3.7.4).
By default, other Layer 3 non-IP headers are truncated at 0 bytes. Truncation is new in version 3.8.0. Truncation is prevented if the "notrunc" anonymization parameter was set.
This function does not anonymize non-IP addresses (e.g., MAC addresses), nor IP addresses in non-IP headers (e.g., ARP).
This function always returns 1.
static int count_and_print_pkt(coral_iface_t *iface, const coral_timestamp_t *timestamp, void *mydata, coral_pkt_buffer_t *buffer, coral_pkt_buffer_t *header, coral_pkt_buffer_t *trailer) { long *countp = mydata; ++(*countp); if (buffer->caplen == buffer->totlen) /* complete capture? */ printf("bytes: %d\n", buffer->caplen); else printf("bytes: %d (of %d)\n", buffer->caplen, buffer->totlen); coral_fprint_pkt(stdout, iface, timestamp, 7, buffer, header, trailer); } int main() { long count; ... count = 0; coral_read_pkts(src, NULL, count_and_print_pkt, NULL, NULL, 0, &count); printf("received %ld packets.\n", count); ... }
The block and cell reading functions may be used only with ATM interfaces that have been started. The cell functions are more general than the block functions. For working with layers 3 and above, the packet reading functions are usually better.
After any of these reading functions are successful,
*cellp will point to a single cell
(for the cell functions)
or array of cells
(for the block functions);
and if binfop is not NULL
,
*binfop will point to a
block info structure
describing the block to which the cell or cells belong.
All structures will be in network byte order. (In version 3.0, cells
read from FATM devices had ATM headers in little endian order.)
binfop may be passed a value of NULL
if the block info will not be
needed.
If timeout is NULL
or omitted,
these functions will wait until data are available or an interrupt occurs.
But if timeout is not NULL
,
these functions will also return after
the amount of time specified in timeout even if there are no data.
If coral_cell_block_hook is not NULL
,
the function to which it points will be called when a new block of ATM cells is
read by any of the cell reading functions.
The deny
protocol rules
are applied by the cell reading functions
to filter the cells and determine their protocol.
They are not applied by the block reading functions.
In either case, no protocol information is given;
use coral_proto_rule to get that.
Note: prior to version 3.4.2, the cell reading functions did not apply
the the configuration deny
rules.
Calls to the different CoralReef reading functions may not be interleaved on a given set of sources.
A call to any CoralReef reading function on a given set of sources invalidates all data in buffers set by previous calls to any reading functions on the same set of sources.
NULL
with errno==0
for EOF,
stopped device, or
expired duration.
(If end-of-file is encountered someplace other than a block boundary, it
is considered an error.)NULL
with errno==EAGAIN
if timeout is exceededNULL
with errno==EBADF
if sources are not ATM.NULL
with other errno value for other errorsNULL
interface pointer for success
coral_iface_t *coral_read_cell(coral_source_t *src,
coral_blk_info_t **binfop,
coral_atm_cell_t **cellp,
struct timeval *timeout);
coral_iface_t *coral_read_cell_all(coral_blk_info_t **binfop,
coral_atm_cell_t **cellp,
struct timeval *timeout);
coral_read_cell()
reads a single cell from the indicated source;
coral_read_cell_all()
reads from all open sources.
If the CORAL_OPT_SORT_TIME
option is off,
coral_read_cell_all()
reads cells in the most
efficient order (i.e., block order);
but if the CORAL_OPT_SORT_TIME
option is on, it will read them
in time-sorted order (interleaving cells from blocks of different interfaces).
If the CORAL_OPT_SORT_TIME
is set,
timeout is ignored (it is always treated as NULL
).
See the section introduction above for more details and return values.
coral_iface_t *coral_read_cell_i(coral_source_t *src,
coral_blk_info_t **binfop,
coral_atm_cell_t **cellp,
coral_interval_result_t *int_result,
struct timeval *interval);
coral_iface_t *coral_read_cell_all_i(coral_blk_info_t **binfop,
coral_atm_cell_t **cellp,
coral_interval_result_t *int_result,
struct timeval *interval);
These functions are like
coral_read_cell()
and coral_read_cell_all()
,
except that there is no timeout and they support intervals.
If the value of interval is greater than 0.0, then
time sorting is automatically enabled regardless of the setting of the
CORAL_OPT_SORT_TIME
option, and
whenever *interval
seconds have passed or EOF is reached,
the functions will return non-NULL
with
*cellp == NULL
to indicate that an interval has ended,
and the start
and end
fields of int_result
will be filled in with the boundaries of the interval.
*binfop
is undefined at the end of an interval.
int_result->stats
is always NULL
.
When EOF is reached, the final partial interval is returned, and the
next call will return NULL
.
See the section introduction above for more details and return values.
coral_iface_t *coral_read_block(coral_source_t *src,
coral_blk_info_t **binfop,
coral_atm_cell_t **cellp,
struct timeval *timeout);
coral_iface_t *coral_read_block_all(coral_blk_info_t **binfop,
coral_atm_cell_t **cellp,
struct timeval *timeout);
The cell reading functions are usually more convenient than these block reading functions.
After a successful read, the number of valid cells in the array pointed to by
*cellp
is indicated by
ntohl((*binfop)->cell_count)
,
the number of bytes (including padding) pointed to by
*cellp
is indicated by
ntohl((*binfop)->blk_size)
,
and the size of a cell is
coral_cell_size(iface)
.
The nth cell in the array pointed to by *cellp which was
read from interface iface can be found with the expression
coral_nth_cell(iface, *cellp, n)
.
coral_atm_cell_t *coral_nth_cell(const coral_iface_t *iface,
coral_atm_cell_t *blk,
int n);
Returns a pointer to the nth cell in the array of cells pointed
to by blk, which was read from iface.
(coral_nth_cell()
is actually defined as a macro.)
void (*coral_cell_block_hook)(const coral_iface_t *iface,
const coral_blk_info_t *binfo);
If coral_cell_block_hook
is not NULL
,
the function to which it
points will be called whenever a cell reading function or packet reading
function reads a new block of ATM cells.
iface and binfo will point to data about the new block.
The default value of coral_cell_block_hook
is NULL
.
int coral_proto_rule(const coral_iface_t *iface,
uint32_t subif,
coral_protocol_t *protop);
This function compares iface and subif (ATM vp:vc) against
the proto
and deny
configuration rules.
If they are denied by the rules, coral_proto_rule
returns 0.
Otherwise, it sets *protop
to the
protocol identifier
according to the rules, and returns 1.
Cells that would be denied by the rules are never returned by the cell API,
but this function is still needed to find the protocol of the PDU to which
a cell belongs or to test for denial of a cell returned by the block API.
If there is no matching
proto
configuration rule for subif, and there is no default
protocol for iface,
the protocol for 0:0 through 0:15 defaults to
CORAL_PROTO_UNKNOWN
,
the protocol for 0:16 defaults to
CORAL_DLT_ILMI
,
and the protocol for all other virtual channels defaults to
CORAL_DLT_ATM_RFC1483
.
Although coral_read_pkt puts IEEE 802.1Q VLAN IDs in the pkt_result->subif field, protocol rules should not be applied to VLAN IDs.
int coral_cell_to_pkt(const coral_iface_t *iface,
coral_atm_cell_t *cell,
coral_pkt_buffer_t *pkt);
Cell is a pointer to the first cell of an AAL5 PDU (in network
byte order).
coral_cell_to_pkt
fills in the object
pointed to by pkt with
information from cell and iface,
for use with functions that expect a
coral_pkt_buffer_t argument.
Iface and the cell's vp:vc are used to determine the protocol of
the data according to the configuration
proto
rules.
If iface is NULL
,
pkt->protocol
will be set to
CORAL_PROTO_UNKNOWN
.
The return value is 0 if
iface and the cell's vp:vc match a configuration
deny
rule, otherwise 1.
const char *coral_file_version(const coral_source_t *src);
Returns a pointer to a static buffer containing a string describing a
file format version.
If src corresponds to a tracefile,
the string describes the file format of the tracefile;
if src is NULL
,
the string describes the current file format (i.e., the highest format version
that this version of libcoral can read, and the format that would be written by
coral_write() in this version of libcoral).
coral_iface_t *coral_next_interface(const coral_iface_t *iface);
coral_source_t *coral_next_source(const coral_source_t *src);
If iface/src is NULL
,
these functions return a pointer to the first CoralReef interface/source;
otherwise, they return a pointer to the interface/source following
iface/src.
They return NULL
if there is no next interface/source.
The order in which interfaces/sources are returned
is not necessarily the order in which they were opened.
These functions are used to step through all interfaces/sources, for example:
coral_source_t *src = NULL; while ((src = coral_next_source(src))) { coral_dump(src); }
coral_iface_t *coral_next_src_iface(const coral_source_t *src,
const coral_iface_t *iface);
Like coral_next_interface(), except it only returns interfaces of src.
const char *coral_source_get_filename(const coral_source_t *src);
Returns the name of the file or network interface of source src,
without a
coral type prefix.
Returns NULL
if src is bad.
const char *coral_source_get_name(const coral_source_t *src);
Returns the name of the source src,
including a
coral type prefix,
if any.
Returns NULL
if src is bad.
const char *coral_source_get_comment(const coral_source_t *src);
Returns a pointer to the comment string from the file header of source
src.
Returns NULL
if src is bad or there is no comment.
int coral_get_source_count(void);
Returns the number of sources.
coral_source_t *coral_interface_get_src(const coral_iface_t *iface);
Returns a pointer to the source to which
interface iface belongs, or NULL
if iface is bad.
int coral_interface_get_type(const coral_iface_t *iface);
Return the original (hardware) type of interface iface, or return CORAL_TYPE_NONE if iface is invalid or its type is unknown.
int coral_source_get_type(const coral_source_t *src);
Return the type of source src, or CORAL_TYPE_NONE if src is invalid or its type is unknown. For live sources, the type will be one of the types listed in the description of coral_interface_get_type(); for file sources, the type will be one of the following:
coral_protocol_t coral_interface_get_datalink(const coral_iface_t *iface);
Return the data link layer type of interface iface,
or CORAL_PROTO_UNKNOWN
if the protocol is unknown,
or -1 if iface is bad.
The data link layer type is one of the CORAL_DLT_*
(layer 2) constants
defined in the
Command Usage document.
coral_protocol_t coral_interface_get_physical(const coral_iface_t *iface);
Return the physical layer type of interface iface,
or CORAL_PROTO_UNKNOWN
if the protocol is unknown,
or -1 if iface is bad.
The physical layer type is one of the CORAL_PHY_*
(layer 1) constants
defined in the
Command Usage document.
int32_t coral_interface_get_bandwidth(const coral_iface_t *iface);
Return the bandwidth (in kilobits per second) of interface iface, or 0 if the bandwidth is unknown, or -1 if iface is bad.
int coral_source_get_number(const coral_source_t *src);
int coral_interface_get_number(const coral_iface_t *iface);
Return a non-negative integer identifier of source src or interface iface, or return -1 if src or iface is bad. The identifier returned is not really useful except as a label. To print an interface number, see coral_fmt_if_subif().
const struct timeval *coral_interface_get_capture_tv(const coral_iface_t *iface);
Returns a pointer to a structure containing the time (relative to the unix
epoch) of the start of the capture on interface iface,
or NULL
if there was an error.
The structure will contain 0,0
if the start time is unknown.
Note: the microsecond component will always be 0 in traces in the old
NLANR and MCI formats and
traces made with CoralReef
versions prior to 3.2.2 (format version 9).
time_t coral_interface_get_capturetime(const coral_iface_t *iface);
Returns the integer component of the value that would be returned by
coral_interface_get_capture_tv(iface)
.
coral_cell_size(const coral_iface_t iface);
Returns the size of the cell structure used by iface.
void coral_read_clock_timespec(const coral_iface_t *iface,
const coral_timestamp_t *t,
struct timespec *ts);
void coral_read_clock_sec_nsec(const coral_iface_t *iface,
const coral_timestamp_t *t,
time_t *sec,
long *nsec);
double coral_read_clock_double(const coral_iface_t *iface,
const coral_timestamp_t *t);
void CORAL_TIMESTAMP_TO_TIMEVAL(const coral_iface_t *iface,
const coral_timestamp_t *t,
struct timeval *tv);
void CORAL_TIMESTAMP_TO_TIMESPEC(const coral_iface_t *iface,
const coral_timestamp_t *t,
struct timespec *ts);
These functions parse the timestamp t, which belongs to a coral_cell_t or coral_pkt_buffer_t read from interface iface, and convert it to a more useful format.
If the CORAL_OPT_NORMALIZE_TIME
option is set, the result will be measured from the unix epoch;
otherwise, the result will have some interface-dependent epoch.
Normalization may introduce some error in the precision; this error will be
the same for all timestamps from the same interface, but may be different
for different interfaces.
These functions automatically correct the case in which the FORE card doesn't
increment the firmware clock because it misses a hardware clock wrap,
unless the CORAL_OPT_FATM_RAW_TIME
option is set.
coral_read_clock_double()
returns the time
as floating point number of seconds.
Note that some precision may be lost by the conversion to double.
coral_read_clock_timespec()
,
coral_read_clock_sec_nsec()
, and
CORAL_TIMESTAMP_TO_TIMEVAL()
splits the time into two integers, seconds and residual fractions of a second,
and writes them into *tv, or *sec and *nsec,
or *ts, respectively.
CORAL_TIMESTAMP_TO_TIMESPEC
is identical to
coral_read_clock_timespec
,
for compatibility with earlier versions of libcoral.
double coral_cell_time_double(const coral_iface_t *iface,
coral_atm_cell_t *cell);
Equivalent to coral_read_clock_double(iface, coral_cell_time(iface, cell))
.
const char *coral_proto_abbr(coral_protocol_t protocol);
const char *coral_proto_desc(coral_protocol_t protocol);
const char *coral_proto_str(coral_protocol_t protocol);
Protocol is a CORAL_prefix_name
constant (listed in the
Command Usage document)
identifying a communication protocol.
These functions return a pointer to a string describing protocol:
coral_proto_abbr
: a short name, or NULL
;coral_proto_desc
: a long description, or NULL
;coral_proto_str
: a long description, or "unknown N".
const char *coral_dns_op_to_str(uint8_t op);
const char *coral_dns_qtype_to_str(uint16_t qtype);
const char *coral_dns_qclass_to_str(uint16_t qclass);
These functions return a pointer to a string describing DNS opcode op, qtype qtype, or qclass qclass, respectively. Strings are taken from http://www.iana.org/assignments/dns-parameters as of the time the library was written; codes not present in that document are formatted as numbers. The return value may point to a static data area that will be overwritten with each call.
uint8_t coral_dns_str_to_op(const char *str);
uint16_t coral_dns_str_to_qtype(const char *str);
uint16_t coral_dns_str_to_qclass(const char *str);
These functions return a code corresponding to str, which is a string describing a DNS opcode op, qtype qtype, or qclass qclass, respectively. Strings are taken from http://www.iana.org/assignments/dns-parameters as of the time the library was written; the return value for a string not present in that document is -1 (cast to the return type).
coral_protocol_t coral_proto_id(const char *name);
Returns a protocol id constant (listed in the
Command Usage document)
corresponding to name, which may be a short abbreviation or a
long description as returned by
coral_proto_{abbr,desc,str}()
.
Returns CORAL_PROTO_ILLEGAL
if name is not a valid protocol name or
abbreviation.
int coral_proto_layer(coral_protocol_t protocol);
Returns the layer number of protocol.
get_vpvc_vp(vpvc)
get_vpvc_vc(vpvc)
set_vpvc_vp(vpvc, vp)
set_vpvc_vc(vpvc, vc)
vp_vc_to_vpvc(vp, vc)
The rotating file API allows a programmer to write to a series of
files, occasionally changing the filename. This can be useful for
long-running processes whose output you may want to read before
the process is complete, help with organizing output data, or simply
to keep output files at a manageable size.
It is usually fairly simple to convert existing code that writes to a
single file into code that writes to a rotating file by replacing
the open and close calls and possibly inserting rotation directives.
If you want the file to rotate every interval, you can use the
CORAL_ROT_AUTO flag, and let libcoral handle everything for you;
if you want more control over when rotations occur, you can call the
coral_rf_start()
and coral_rf_end()
functions yourself.
The functions:
coral_rotfile_t *coral_rf_open_fd(int *fdp,
const char *name,
const char *tmp,
uint8_t flags);
coral_rotfile_t *coral_rf_open_file(FILE **filep,
const char *name,
const char *tmp,
uint8_t flags);
coral_rotfile_t *coral_rf_open_gzfile(coral_rf_info_gz_t *fp,
const char *name,
const char *tmp,
uint8_t flags);
coral_rotfile_t *coral_rf_open_ogzfile(coral_rf_info_ogz_t *fp,
const char *name,
const char *tmp,
uint8_t flags);
coral_rotfile_t *coral_rf_open_pcap_dump(coral_rf_info_pcap_dump_t *fp,
const char *name,
const char *tmp,
uint8_t flags);
Creates a coral_rotfile_t object to be used for writing a series of files.
An iteration of the coral_rotfile_t can be started
either manually with coral_rf_start()
,
or automatically at the beginning of each interval
if flags has the CORAL_ROT_AUTO bit set.
When an iteration is started, the object
pointed to by the
first parameter is filled in with a
file descriptor, FILE pointer,
coral_rf_info_gz_t, coral_rf_info_ogz_t,
or coral_rf_info_pcap_dump_t.
Then, that value can be used as the destination of appropriate writing
functions.
Name should contain % conversion specifiers; these will be replaced each time the underlying file is rotated. The following conversions are recognized:
%i
- iteration counter (starting at 0)
%s
- seconds (from the tv parameter of
coral_rf_start()
)
%f
- 6 digits of fractional seconds (from the tv
parameter of coral_rf_start()
)
%F
- equivalent to %Y-%m-%d
in strftime()
All other % specifiers will be replaced as in strftime(),
using the tv parameter of coral_rf_start()
.
Additionally, all specifiers other than %f
may contain any of the
modifiers allowed in %s
by printf (e.g., "%03i"
).
All specifiers other than %s
are formatted in the
local timezone according to the TZ
environment variable;
to use UTC instead, set TZ="UTC"
in the environment.
If tmp is NULL, a file with the specified name
is opened immediately with each call to coral_rf_start()
;
otherwise, a temporary file is used, which is renamed to the specified
name when coral_rf_end()
is called.
If tmp is not "", it is used as the name of the temporary file;
if tmp is "", a temporary name is generated automatically,
with the same directory as name.
To allow the programmer to write code that unconditionally uses the coral_rf functions for standard output as well as files, the created rotfile object will behave differently if name is "-":
coral_rf_start()
other than the first have no effect
coral_rf_end()
have no effect
If flags has the CORAL_ROT_AUTO bit set,
the rotfile will rotate automatically at the beginning of every interval of
coral_read_pkt
or coral_read_pkts
.
But if name did not contain any "%" specifiers, only the first
(possibly implicit) interval
will cause an automatic coral_rf_start
call; thus, without "%",
the file will not rotate every interval, but you still do not
need to call coral_rf_start
manually before the first write.
Whatever the setting of CORAL_ROT_AUTO, you can still call
coral_rf_end
and coral_rf_start
to
manually rotate the rotfile.
But if flags does not contain
CORAL_ROT_AUTO, or if you want to write to the rotfile
before the first interval, you must call coral_rf_start
manually at least once before writing to the file.
If the filename generated from name by coral_rf_start
would
be a duplicate of a previously used name, it will automatically append
an iteration counter to the filename to avoid overwriting previous files.
This safety mechanism will be disabled if flags
has the CORAL_ROT_UNSAFE bit set.
These functions return
a pointer to a newly created coral_rotfile_t
if successful; failure is indicated by returning NULL with errno set
and printing a message with coral_diag()
.
Typical rotating file code has this structure:
FILE *file; coral_rotfile_t *rf; rf = coral_rf_open_file(&file, name, NULL, 0); coral_rf_start(rf); while (there is data) { if (it is time to rotate the file) { coral_rf_end(rf); coral_rf_start(rf); } fputs(data, file); } coral_rf_close(rf);
If you wanted to rotate on interval boundaries, you could use the CORAL_ROT_AUTO flag and omit the calls to coral_rf_start and coral_rf_end.
coral_rotfile_t *coral_rf_open(void *info,
const char *name,
const char *tmp,
uint8_t flags,
int (*open)(const char *name, void *info),
int (*close)(void *info));
Like the coral_rf_open_* functions, coral_rf_open creates a coral_rotfile_t object to be used for writing a series of files. The name, tmp, and flags parameters are as described under coral_rf_open_fd. The open and close parameters are callback functions that are called by coral_rf_start and coral_rf_end, respectively; these allow you to define custom functions to operate on any file type, instead of just the predefined types used by coral_rf_open_*. The info parameter is like the first parameter of coral_rf_open*, except the type of the object to which it points is defined by the open and close parameters.
Whenever the rotfile needs to rotate, it uses the open and close
callback functions to open and close the real file.
info is a pointer to whatever data is required by the callback functions.
The object to which info points must remain valid for the lifetime
of the rotfile.
Libcoral provides several pairs of useful callback functions of the form:
int coral_rf_cb_open_filetype(const char *name,
void *info);
int coral_rf_cb_close_filetype(void *info);
filetype | info type | description |
fd
| int* | Opens a file descriptor, stored in *info .
|
file
| FILE** | Opens a stdio FILE, stored in *info .
|
gzfile
| coral_rf_info_gz_t* | Opens a gzipped file. You must set info->mode before opening.
The file pointer is stored in info->gzfile .
|
ogzfile
| coral_rf_info_ogz_t* | Opens a gzipped file if the file's name ends in ".gz" or if the
global gzip option was set with the "gzip" command
or coral_set_gzip(), otherwise it opens an uncompressed file.
To write to an ogzfile, you must use the coral_rf_ogz_*
functions.
|
pcap_dump
| coral_rf_info_pcap_dump_t* | Opens a pcap file. You must set info->pcap before opening.
The file pointer is stored in info->pcap_dumper .
Opens a gzipped file if the file's name ends in ".gz" or if the
global gzip option was set with the "gzip" command
or coral_set_gzip(), otherwise it opens an uncompressed file.
|
These five pairs of callbacks are used to implement the
coral_rf_open_* functions.
The gzfile
and ogzfile
callbacks will be available only if a
good version of libz was found when libcoral was compiled.
You can also pass pointers to your own open and close functions
that open different kinds of files and/or write headers or trailers
on the files. In this way, you can have custom rotating files that have
the same filename formatting and other features of the standard libcoral
rotfile types. Any open function passed to coral_rf_open()
must handle the "-" filename.
If it is possible to write your open function to work with a file descriptor
or FILE* instead of the filename, you can make it call
coral_rf_cb_open_fd()
or coral_rf_cb_open_file()
to be sure it behaves the same way (e.g., for handling the filename "-").
For example, coral_rf_cb_open_file()
is actually a very simple function
that calls coral_rf_cb_open_fd()
and then passes the resulting file
descriptor to fdopen()
.
The following example of a custom open function uses
coral_rf_cb_open_file()
to open a regular file, and also writes a header at the top of each rotated
file. This is the easiest way to guarantee that the header will be written
exactly once at the start of each iteration, even if the rotfile
doesn't actually rotate (because it is directed to stdout, for example).
int open_outfile(const char *name, void *info) { FILE *file; if (coral_rf_cb_open_file(name, info) < 0) return -1; file = *(FILE**)info; fprintf(file, "%17s %7s %7s\n", "start", "pkts", "bytes"); return 0; }
coral_rf_open()
returns a pointer to a newly created coral_rotfile_t
if successful; failure is indicated by returning NULL with errno set
and printing a message with coral_diag()
.
void *coral_rf_ogz_write(coral_rf_info_ogz_t *info,
const void *buf,
size_t len);
void *coral_rf_ogz_seek(coral_rf_info_ogz_t *info,
off_t offset,
int whence);
void *coral_rf_ogz_flush(coral_rf_info_ogz_t *info);
These functions are used to operate on info, which must point to a
coral_rf_info_ogz_t opened by
coral_rf_open_ogzfile()
or
coral_rf_cb_open_ogzfile()
.
They are similar to their standard C counterparts, except that
they take a pointer to a coral_rf_info_ogz_t instead of a file descriptor.
Unlike fseek(), coral_rf_ogz_seek()
will work on a pipe open
for writing, if whence == SEEK_CUR and offset >= 0.
Remember that coral_rf_ogz_seek()
followed by
coral_rf_ogz_close()
will not write trailing zeros to the file
(just like fseek() followed by fclose() on a standard file).
Prior to CoralReef version 3.9.0, the offset parameter to
coral_rf_ogz_seek()
was a long, not an off_t.
void *coral_rf_info(coral_rotfile_t *rf);
Returns
the first parameter that was passed in to the
coral_rf_open*()
function that created rf.
int coral_rf_start(coral_rotfile_t *rf,
const struct timeval *tv);
Starts an iteration of rotating file rf which has been opened by
one of the coral_rf_open
functions.
The filename is fixed at this point
using the time value in tv for the strftime expansion.
If tv is NULL
, the current time is used.
If temporary files were requested when rf was opened, this filename
is not actually used yet, it is just recorded for later use.
Next, a real file is actually opened, unless the filename was "-"
and this is not the first call to coral_rf_start
.
If a disk file is opened,
it will have mode 666 modified by the process umask.
Returns 0 for success;
failure is indicated by returning -1 with errno set and printing a
message with coral_diag()
.
See coral_rf_start_name
and coral_rf_start_output
for a fork-safe equivalent of this function.
int coral_rf_start_name(coral_rotfile_t *rf,
const struct timeval *tv);
int coral_rf_start_output(coral_rotfile_t *rf);
These two functions provide a fork-safe equivalent to coral_rf_start
,
which is useful if you want to use a child process to write output for one
interval so the parent process can begin processing the next interval
immediately.
Before forking, you should call coral_rf_start_name
.
After forking, in the child process, you should
call coral_rf_start_output
, do your writing, and eventually
call coral_rf_end
and _exit()
.
You should not call coral_rf_end
in the parent.
int coral_rf_end(coral_rotfile_t *rf);
Ends an iteration of rf by
closing the real file associated with this iteration of the rotfile,
unless the filename was "-".
If temporary files were requested when rf was opened, the
file that was created by coral_rf_start()
is now renamed to the permanent file name.
The iteration counter of rf is incremented (this counter appears
in place of "%i" in the filename created by coral_rf_start()
).
Writing to the file associated with rotfile
is not allowed until rf is started again with coral_rf_start()
.
If the filename was "-", or
coral_rf_start(rf)
has not been called since
rf was opened or ended,
this function has no effect.
Returns 0 for success;
failure is indicated by returning -1 with errno set and printing a
message with coral_diag()
.
int coral_rf_close(coral_rotfile_t *rf);
Implicitly calls coral_rf_end(rf)
if necessary,
and deallocates all resources associated with rf.
To guarantee that all data is actually written to a file,
it is important to call coral_rf_close before exiting the program.
Returns 0 for success;
failure is indicated by returning -1 with errno set and printing a
message with coral_diag()
.
int coral_rotate_errfile(const struct timeval *tv);
Rotates the error file
(if the configured error file name contained "%"),
using tv as the timestamp for substitutions in the filename
as in coral_rf_start()
.
Returns 0 for success;
failure is indicated by returning -1 with errno set and printing a
message with coral_diag()
.
If rotation fails, the error file resets to stderr.
The writing API allows a programmer to copy cells or blocks from a CoralReef source to a CoralReef-format trace file. The source is typically a OCx device (for doing data capture), but may also be another trace file (useful for encoding, or converting from another format).
For information on writing packets in pcap format, see the section on pcap conversion.
coral_writer_t *coral_write_open(const char *name);
Open file name for writing a trace file in CoralReef format.
If the name ends in ".gz"
or the
"gzip" configuration option was
given, and CoralReef was compiled with libz, the file will be gzipped.
(coral_set_api() must be called with the CORAL_API_WRITE bit
to enable the "gzip" configuration option.)
A leading ~
in name is expanded to a home directory.
If the name is "-"
, data will be written to stdout.
Returns a pointer to a coral writer
for success, NULL
for failure.
The recommended suffix for CoralReef trace files is ".crl", and for encoded
CoralReef trace files is ".enc.crl".
To ensure that all data from all sources are read, you must call
coral_stop()
on any sources which have not reached EOF.
Then, to ensure that all data from all sources are written, you must call
coral_write_close()
on the writer, before calling
coral_close()
on the sources.
coral_writer_t *coral_write_rfopen(const char *name,
const char *tmp);
Like coral_write_open()
, except the file can be rotated.
The file name should contain % escapes; these will get expanded with
every rotation. The legal escapes are the same as those in
coral_rf_open()
.
The underlying file is not actually opened until
coral_rf_start()
or the first write;
the timestamp used in filename expansion is the current time.
Use coral_write_end()
to end the current iteration
of a file; a new iteration will be started with the next
coral_rf_start()
or write.
Use coral_write_close()
when done writing to the file;
it will do an implicit coral_write_end()
if one has
not been done since the last coral_rf_start()
or write.
If tmp is not NULL, the current iteration file will be given a
temporary name, which will be renamed to the permanent name
by coral_write_end()
; this guarantees that files matching
name are always complete. If tmp is not "", it is used as
the temporary name; if it is "", a temporary name is generated automatically,
with the same directory as name.
coral_writer_t *coral_write_fdopen(int fd);
Like coral_write_open, except it uses the already-open file descriptor fd instead of a filename.
Mixing CoralReef operations with other operations on descriptor fd may have unpredictable effects.
const char *coral_write_get_name(coral_writer_t *writer);
Returns the filename used to open writer.
int coral_write_set_comment(coral_writer_t *writer,
const char *comment);
int coral_write_set_encoding(coral_writer_t *writer,
const char *encoding);
These functions set the comment or encoding strings that will be written into the file header of writer. The string parameters are null-terminated strings; comment may be up to 255 characters, encoding may be up to 31 characters. These functions return 0 for success, -1 for failure.
int coral_write_init_all(coral_writer_t *writer);
int coral_write_init_source(coral_writer_t *writer,
coral_source_t *src);
Prepare to write data from the indicated sources to writer. Returns 0 for success, -1 for failure.
int coral_write_init_interface(coral_writer_t *writer,
coral_iface_t *iface);
Prepare to write data from a single interface iface to tracefile writer. Returns 0 for success, -1 for failure.
int coral_write_cells(coral_writer_t *writer,
const coral_iface_t *iface,
const coral_atm_cell_t *cell,
int count);
Write an array of count cells pointed to by cell to writer. iface indicates which interface the cells were read from (as returned by a CoralReef reading function). Returns 0 for success, -1 for failure.
int coral_write_block(coral_writer_t *writer,
const coral_iface_t *iface,
const coral_blk_info_t *binfo,
const coral_atm_cell_t *blk);
Write a block of cells pointed to by blk
with block info binfo to writer.
The structure pointed to by binfo must be in network byte order.
iface indicates which interface the cells were read from
(as returned by a CoralReef reading function).
This function is more efficient than coral_write_cells()
.
Returns 0 for success, -1 for failure.
int coral_write_close(coral_writer_t *writer);
Close the coral trace indicated by writer.
Returns 0 for success, -1 for failure.
To ensure that all data from all sources are read, you must call
coral_stop()
on any sources which have not reached EOF.
To ensure that all data from all sources are written, you must call
coral_write_close()
on the writer, before calling
coral_close()
on the sources.
int main(int argc, char *argv[]) { coral_writer_t *writer; coral_iface_t *iface; coral_atm_cell_t *blk; coral_blk_info_t *binfo; coral_set_duration(60); if (coral_config_arguments(argc, argv) < 0) exit(2); writer = coral_write_open("out.crl"); if (!writer) exit(3); if (coral_write_init_all(writer) < 0) exit(4); if (coral_start_all() < 0) exit(5); while ((iface = coral_read_block_all(&binfo, &blk, NULL))) { if (coral_write_block(writer, iface, binfo, blk) < 0) exit(6); } coral_stop_all(); coral_write_close(writer); coral_close_all(); }
These functions convert CoralReef structures to pcap structures, so they may be used with pcap and BPF functions. To use these functions, the pcap header must be included:
#include <pcap.h>
pcap_t *coral_iface_to_pcapp(coral_iface_t *iface);
pcap_t *coral_iface_to_pcapp_raw(coral_iface_t *iface);
Returns a pointer to a pcap_t containing information copied from
*iface,
or returns NULL
if there is an error.
If coral_iface_to_pcapp_raw is called, or coral_iface_to_pcapp
is called but iface uses a data link layer protocol not supported
by pcap, the created pcap_t structure will be set to DLT_RAW (raw IP), and
coral_pkt_to_pcap() calls on the pcap_t
will strip encapsulation from IP packets and discard non-IP packets.
The caller must not pcap_close()
or free()
the
resulting pcap_t; libcoral will do this automatically when iface
is closed.
(Prior to version 3.4, it was the caller's responsibility to free the pcap_t.)
int coral_iface_to_pcap(const coral_iface_t *iface,
pcap_t *pcap);
Obsolete. See coral_iface_to_pcapp().
int coral_pkt_to_pcap(coral_iface_t *iface,
const coral_timestamp_t *timestamp,
const coral_pkt_buffer_t *pkt,
pcap_t *pcap,
struct pcap_pkthdr *hdr);
Parameters:
This function
fills in *hdr with information from
*iface, *timestamp, and *pkt.
If *timestamp is not NULL
,
its value will be normalized to the unix epoch and copied to
hdr->ts
;
otherwise, hdr->ts
will be set to zero.
(The timestamp was not normalized in versions before 3.2.2.)
The linktype of pcap must be either DLT_RAW
or compatible with the protocol of iface.
The former condition is true if pcap was created by calling
coral_iface_to_pcapp_raw().
The latter condition is true if pcap was created by calling
coral_iface_to_pcapp() on
iface or another coral interface with the same protocol
as iface.
If the linktype of pcap is compatible with the protocol of iface, this function simply copies and converts the information into hdr, and returns 0.
If the linktype of pcap is DLT_RAW
,
this function will strip off the encapsulation to find an IP packet.
If there is no IP packet, this function returns -1.
If there is an IP packet, this function returns the offset of that IP packet
within pkt->buf
, and fills in the rest of
hdr with information about the IP packet, not the original packet.
This function returns -1 to indicate an error or that the packet could not be converted to pcap form.
int coral_write_pkt_to_pcap(coral_iface_t *iface,
const coral_timestamp_t *timestamp,
const coral_pkt_buffer_t *pkt,
pcap_t *pcap,
struct pcap_dumper_t *pcap_dumper);
This function calls coral_pkt_to_pcap()
to convert the CoralReef packet pkt to a pcap packet,
and writes it to pcap_dumper with pcap_dump()
.
This example reads packets from a CoralReef interface and writes them to a tcpdump file.
pcap_t *pcap; struct pcap_pkthdr pcap_hdr; int offset; /* ... */ pcap = coral_iface_to_pcapp(iface); if (!pcap) /* handle error */; pcap_dumper = pcap_dump_open(pcap, filename); /* ... */ iface = coral_read_pkt(&pkt_result, &interval_result); if (!iface) /* handle error */; offset = coral_pkt_to_pcap(iface, pkt_result.timestamp, pkt_result.packet, &pcap_hdr); if (offset < 0) /* handle error */; pcap_dump(pcap_dumper, &pcap_hdr, pkt_result.packet->buf + offset);
Note: in the example above, it is possible to open a pcap dumper for coral interface A, and then dump packets to it that were read from coral interface B. This is ok only if interfaces A and B have the same data link type, bandwidth, and other properties; otherwise, coral_pkt_to_pcap() will return an error without writing the incompatible packet.
The header <crl_byteorder.h>
defines a set of macros
for manipulating the byte order of 16, 32, and 64 bit integer values.
BYTE_ORDER
or WORDS_BIGENDIAN
must be defined
when <crl_byteorder.h>
is included.
BYTE_ORDER
is defined in <sys/param.h>
on some platforms,
and WORDS_BIGENDIAN
is defined by <coral-config.h>
or can be
defined by a GNU configure script.
These macros can be optimized to a compile-time constant when their
parameter is a compile-time constant.
Each macro with a name of the form crl_srctodsttype takes one integer parameter in byte order indicated by src and returns an integer in byte order type indicated by dst. The type of the parameter is indicated by type. The following byte order macros are defined:
type of parameter and result | |||
byte order conversion | uint16_t | uint32_t | uint64_t |
host to big endian | crl_htobes | crl_htobel | crl_htobe64 |
big endian to host | crl_betohs | crl_betohl | crl_betoh64 |
host to little endian | crl_htoles | crl_htolel | crl_htole64 |
little endian to host | crl_letohs | crl_letohl | crl_letoh64 |
host to network | crl_htons | crl_htonl | crl_hton64 |
network to host | crl_ntohs | crl_ntohl | crl_ntoh64 |
uint16_t crl_nptohs(void *p);
uint32_t crl_nptohl(void *p);
Converts the value pointed at by p from network order to host order. The value pointed at by p does not need to be aligned, so these are safe to use on fields within packets returned by libcoral.
int coral_puts(const char *str);
Like the standard C function puts(str)
, except that it prints to the
CoralReef errfile instead of stdout,
and it is guaranteed to not modify errno
.
int coral_printf(const char *fmt,
...);
Like printf(fmt, ...)
,
except that it prints to the CoralReef errfile instead of stdout,
and it is guaranteed to not modify errno
.
void coral_diag(int level,
(const char *fmt, ...));
Like coral_printf(fmt, ...)
,
except that nothing will be printed if
level > coral_get_verbosity()
.
Returns void.
void coral_fprint_data(FILE *file,
int indent,
const u_char *data,
size_t len);
void coral_print_data(int indent,
const u_char *data,
size_t len);
coral_print_data
prints len bytes from data
to stdout
in a easily readable format:
16 hex values per line, with each line indented indent spaces.
coral_fprint_data
is like
coral_print_data
, except
it prints to file instead of stdout
.
void coral_fprint_cell(FILE *file,
int indent,
const coral_iface_t *iface,
const coral_atm_cell_t *cell);
void coral_print_cell(int indent,
const coral_iface_t *iface,
const coral_atm_cell_t *cell);
coral_print_cell
prints cell (which was read from iface) to stdout
in an easily readable format, with the timestamp in seconds, the
ATM header expanded by fields, and the payload in hex,
with each line indented indent spaces.
This format is used by the application crl_print
.
coral_fprint_cell
is like coral_print_cell
, except
it prints to file.
void coral_fmprint_pkt(FILE *file,
coral_iface_t *iface,
const coral_timestamp_t *timestamp,
int minlayer,
int maxlayer,
coral_pkt_buffer_t *packet,
coral_pkt_buffer_t *header,
coral_pkt_buffer_t *trailer);
coral_fmprint_pkt
prints packet and optionally
header and trailer
(which were read from iface) to file
in an easily readable format, with the timestamp in seconds.
Protocol layers less than minlayer will be skipped;
layers between minlayer and maxlayer will be
expanded by fields in an easily readable format,
as by coral_fmt_get_payload()
;
layers greater than maxlayer or not understood by libcoral
will be printed in hex.
This format is used by the application crl_print_pkt
.
void coral_fprint_pkt(FILE *file,
coral_iface_t *iface,
const coral_timestamp_t *timestamp,
int maxlayer,
coral_pkt_buffer_t *packet,
coral_pkt_buffer_t *header,
coral_pkt_buffer_t *trailer);
Equivalent to
coral_fmprint_pkt(iface, timestamp,
1, maxlayer, packet,
header, trailer)
.
void coral_mprint_pkt(coral_iface_t *iface,
const coral_timestamp_t *timestamp,
void *layerp,
coral_pkt_buffer_t *packet,
coral_pkt_buffer_t *header,
coral_pkt_buffer_t *trailer);
void coral_print_pkt(coral_iface_t *iface,
const coral_timestamp_t *timestamp,
void *layerp,
coral_pkt_buffer_t *packet,
coral_pkt_buffer_t *header,
coral_pkt_buffer_t *trailer);
These functions are like coral_fmprint_pkt()
,
except they print to stdout
, and the layers are specified
differently.
For coral_mprint_pkt()
, layerp is a pointer
to an array of two integers containing
minlayer and maxlayer.
For coral_print_pkt()
, layerp is a pointer
to a single integer containing maxlayer;
minlayer defaults to 1.
The odd syntax for specifying layers makes these functions
suitable for use as a
coral_pkt_handler for
coral_read_pkts().
int coral_fmt_if_subif(char *buf,
coral_iface_t *iface,
uint32_t subif);
coral_fmt_if_subif
prints a formatted
representation of iface id and subif into buf.
The size of buf should be at least
CORAL_FMT_IF_SUBIF_LEN
.
If the data link type of iface does not have subinterfaces,
the format is just the interface number
(coral_interface_get_number);
if it does, the format is
"if[subif]", where subif is formatted as by
coral_fmt_subif()
.
This function returns the length of the formatted string.
int coral_fmt_subif(char *buf,
coral_iface_t *iface,
uint32_t subif);
coral_fmt_subif
prints a formatted
representation of subifinto buf.
The size of buf should be at least
CORAL_FMT_SUBIF_LEN
.
The format depends on the data link type of iface:
This function returns the length of the formatted string.
void coral_dump(const coral_source_t *src);
void coral_dump_all(void);
Prints information about the indicated sources to the CoralReef errfile,
like the application crl_info
.
void coral_stats(const coral_source_t *src);
void coral_stats_all(void);
Prints statistics about the indicated sources to the CoralReef errfile.
size_t coral_fwrite_binint(FILE *file,
uint8_t *p);
size_t coral_fwrite_binint(FILE *file,
uint16_t *p);
size_t coral_fwrite_binint(FILE *file,
uint32_t *p);
size_t coral_fwrite_binint(FILE *file,
uint64_t *p);
coral_fwrite_binint
writes integer *p to file file
as an opaque but portable binary value.
If *p is of type uint8_t, uint16_t, or uint32_t, it will be written
straightforwardly in network byte order.
But if *p is uint64_t, its value must be less than 262,
and it will it will be written in a compressed format that occupies only
1 byte if the value < 26,
or 2 bytes if the value < 214,
or 4 bytes if the value < 230,
or 8 bytes otherwise.
This can result in a significant space saving in applications that need to
support values up to 262 - 1 even though the values are frequently
much smaller.
coral_fwrite_binint
returns 1 if the integer was written
successfully, 0 otherwise.
coral_fwrite_binint
is actually a macro.
size_t coral_fread_binint(FILE *file,
uint8_t *p);
size_t coral_fread_binint(FILE *file,
uint16_t *p);
size_t coral_fread_binint(FILE *file,
uint32_t *p);
size_t coral_fread_binint(FILE *file,
uint64_t *p);
coral_fread_binint
reads a binary integer written by
coral_fwrite_binint
from file and places its value
in *p.
The type of *p must match the type used to write the integer with
coral_fwrite_binint
.
Like fread(), coral_fread_binint
returns 1 if the integer was read
successfully, 0 otherwise; you can use
ferror(file) or feof(file)
to determine if a failure was due to error or end of file.
coral_fread_binint
is actually a macro.
char *coral_filename(const char *str,
char *dst,
size_t len);
Copies str to dst,
with any leading "~name/
" replaced with the home directory of user
name, and any leading "~/" replaced with the home directory of the user
who owns the process.
At most len - 1
characters will be written into
dst. (A typical value for len is PATH_MAX
,
defined in <limits.h>
.)
If dst is NULL
,
coral_filename()
will malloc len bytes for it before writing to it. It is the
caller's responsibility to free the allocated memory.
The return value is a pointer to the buffer containing the expanded filename,
or NULL
if coral_filename()
could not allocate the required memory.
#include <sys/types.h>
#include <sys/socket.h>
int coral_inet_pton(int af,
const char *src,
void *dst);
Same as inet_pton(), for hosts that don't have inet_pton() or inet_aton(). (Note that inet_addr() is unable to distinguish between the IPv4 address 255.255.255.255 and an error.) Converts an address string in src to an internal form in dst according to the address family af. Valid values for af are AF_INET and AF_INET6.
#include <arpa/inet.h>
int coral_inet_ntop(int af,
const void *src,
char *dst,
int dstlen);
Same as inet_ntop(), for hosts that don't have inet_ntop() or inet_ntoa(). Converts an IPv4 or IPv6 address in src to a string in dst according to the address family af. Valid values for af are AF_INET and AF_INET6.
uint32_t coral_in_cksum_add(uint32_t psum,
const void *data,
int len);
uint16_t coral_in_cksum_result(uint32_t psum);
Calculates the internet checksum of the string in data. Usage:
psum
to 0psum =
coral_in_cksum_add(psum, data, len)
for each segment of buffer,
where data is a pointer to the segment
and len is the length of the segmentcoral_in_cksum_result(psum)
to get result.Segments must be short-aligned. Entire message must have length less than 32768.
int coral_sendblk(coral_source_t *src,
int ndesc);
Incomplete.
The definitions here are not necessarily complete; actual structures may contain undocumented fields that should not be accessed by the programmer.
int8_t, int16_t, int32_t, int64_t,
uint8_t, uint16_t, uint32_t, uint64_t
If these are not already defined on your platform,
<libcoral.h>
will define them.
An opaque structure representing a source of network traffic: either a tracefile or a real network device. See the Introduction.
An opaque structure representing a single network device within a source (since a tracefile may contain data from multiple devices). See the Introduction.
The coral_io_mode_t structure describes device options. See coral_set_iomode for a description of the possible flag values.
typedef struct { u_int flags; /* options */ int first_n; /* number of bytes to read per packet */ } coral_io_mode_t;
An opaque structure representing a file to which the coral_write functions will write.
An opaque interface-specific timestamp format that should be accessed through the coral_read_clock functions.
A protocol identifier. See the protocols section of the Command Usage document.
The coral_blk_info_t structure defined in <libcoral.h>
is used by many functions. All members are in network byte order.
It has at least these members:
u_int interface; /* which card this came from, if * applicable */ u_int blk_size; /* number of bytes in block */ u_int cell_count; /* number of valid cells in this blk */ u_int cells_lost; /* number of cells lost during block */ u_int unknown_vpi_vci;/* cells dropped because vpi/vci * unknown */ struct timespec tbegin; /* time of block start */ struct timespec tend; /* time of block end */
Note that the interface
field may not correspond to
the number of the iface pointer returned by the
CoralReef reading functions.
The atm_hdr.h
structure will only be available if
BYTE_ORDER
or WORDS_BIGENDIAN
is defined
when <libcoral.h>
is included.
(BYTE_ORDER
is defined in <sys/param.h>
on some platforms,
and WORDS_BIGENDIAN
can be defined by a GNU configure script.)
The programmer must ensure that atm_hdr.ui
is in host byte order
before accessing fields of atm_hdr.h
.
union atm_hdr { struct { uint32_t gfc : 4; /* generic flow control */ uint32_t vpvc : 24; /* virtual path + circuit indicators */ uint32_t oam_rm : 1; /* PTI: OAM/RM indicator (ie, not user data) */ uint32_t congestion : 1; /* PTI: we don't use this */ uint32_t sdu_type : 1; /* PTI: in AAL5, this marks end of SAR-SDU */ uint32_t clp : 1; /* cell loss priority */ } h; uint32_t ui; };
As of version 3.3, the ATM cell record structure is not directly accessible;
coral_atm_cell_t
is just void
.
All access to the fields of a cell record must be done with the
accessor functions below. This is so libcoral can support different record
layouts used by different hardware, firmware, and drivers.
Any of the accessors that return a pointer may return NULL
if the field is not available because of hardware, firmware, or driver options.
The iface parameter of each accessor macro must be the interface from which cell was read.
const coral_timestamp_t *coral_cell_time(iface,
cell);
const union atm_hdr *coral_cell_header(iface,
cell);
const char *coral_cell_hec(iface,
cell);
const char *coral_cell_payload(iface,
cell);
size_t coral_cell_size(iface);
Iface is a (coral_iface_t *)
pointing to the interface
from which cell was read. Cell is a
(coral_atm_cell_t *)
pointing to the cell record from which the
field will be read. Any of the accessor functions that return a pointer may
return NULL
if the corresponding field is not present in the cell
structure for the given interface.
The old version of the structure is documented here for reference only.
typedef struct { coral_timestamp_t t; /* timestamp, in card-specific format */ union atm_hdr cu; /* ATM header (without HEC) */ union { char payload[48]; short payload_shorts[24]; u_int payload_i[12]; } p; /* ATM cell payload == SAR-PDU */ } coral_atm_cell_t; /* obsolete - for reference only */
typedef struct { uint8_t cpcs_uu; /* CPCS user-to-user indication */ uint8_t cpi; /* common part indicator */ uint16_t length; /* length of CPCS PDU payload */ uint32_t crc; /* cyclic redundancy check of CPCS PDU */ } aal5_trailer_t;
typedef struct { uint8_t llc_dsap; uint8_t llc_ssap; uint8_t llc_cntl; uint8_t snap_org[3]; uint16_t snap_type; } coral_llcsnap_t;
typedef struct { int caplen; /* length of data actually captured in buf */ int totlen; /* total length of pkt (negative if unknown) */ const char *buf; /* data (aligned to a multiple of 4 bytes) */ coral_protocol_t protocol; /* protocol */ ... } coral_pkt_buffer_t;
typedef struct { uint64_t l2_recv; /* Layer 2 PDUs received */ uint64_t l2_drop; /* Layer 2 PDUs dropped */ uint64_t pkts_recv; /* packets received */ uint64_t pkts_drop; /* packets dropped */ uint64_t truncated; /* packets truncated by insufficient capture */ uint64_t driver_corrupt; /* cell looks bad from the capture device */ uint64_t too_many_vpvc; /* too many simultaneous vpvc pairs */ uint64_t buffer_overflow; /* AAL5 cell stream > MAX_PACKET_SIZE */ uint64_t aal5_trailer; /* AAL5 trailer had bad length */ uint64_t ok_packet; } coral_pkt_stats_t;
The l2_recv
and l2_drop
fields count layer 2 PDUs
(e.g., ATM cells), and may not be totally accurate.
On interfaces that operate on blocks (i.e., POINT, FORE ATM, and DAG),
the layer 2 PDUs reported are those belonging to every block that started
within the interval. If there are many blocks per interval the error should
be small, but if traffic is low the error is more significant.
If you require more accurate per-block data, use
coral_cell_block_hook.
Most types of interfaces set only a subset of these statistics (the rest will always be zero):
l2_recv
,
l2_drop
,
pkts_recv
,
truncated
,
driver_corrupt
,
too_many_vpvc
,
buffer_overflow
,
aal5_trailer
pkts_recv
,
pkts_drop
,
truncated
pkts_recv
,
pkts_drop
(see also dropinterval)
pkts_recv
,
truncated
typedef struct { const coral_timestamp_t *timestamp; /* time packet was read */ coral_pkt_buffer_t *packet; /* link or sub-network layer packet */ coral_pkt_buffer_t *header; /* link layer header (eg, ATM) */ coral_pkt_buffer_t *trailer; /* link layer trailer (eg, AAL5) */ uint32_t subiface; /* sub-interface id (ATM VPVC or VLAN ID) */ } coral_pkt_result_t;
The subiface
field can be formatted with
coral_fmt_subif().
typedef struct { struct timeval begin; /* beginning of interval */ struct timeval end; /* end of interval */ coral_pkt_stats_t *stats; /* packet statistics for interval */ } coral_interval_result_t;
An opaque structure that should be accessed through the coral_rf_* functions.
typedef struct { const char *gzmode; void *gzfile; } coral_rf_info_gz_t;
typedef struct { pcap_dumper_t *pcap_dumper; pcap_t *pcap; } coral_rf_info_pcap_dump_t;