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.
Compiling
All CoralReef programs should include these headers:
#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.
CoralReef programs should link with -lcoral
,
-lpcap
(if libcoral was compiled with pcap support), and
-lz
(if libcoral was compiled with zlib support).
The API
Command-line Configuration
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[]);
-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);
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 resposibility 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);
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);
coral_config_arguments()
,
coral_config_options()
, or coral_config_command()
is used.
int coral_usage(const char *appname, const char *argmsg, ...);
NULL
,
it use 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>...
Global Configuration
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.
int coral_set_api(int api);
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() |
The api parameter may optionally be bitwise-ORed with this constant, if coral_write will be used:
API | allowed configuration commands | allowed functions |
CORAL_API_WRITE
|
gzip
|
coral_set_gzip()
|
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()
read cells 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.
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.
int coral_set_iomode(int off, int on, int first, int fixed);
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:
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.
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.
int coral_set_verbosity(int verbosity); int coral_get_verbosity(void);
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);
count | affected APIs |
max_pkts | packet |
max_cells | cell |
max_blks | block and cell |
int coral_set_comment(const char *comment); const char *coral_get_comment(void);
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);
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.
int coral_set_interval(struct timeval *interval); int coral_get_interval(struct timeval *interval);
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 timestamps to test for intervals, so 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.
int coral_set_gzip(const str *mode);
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);
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);
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, int off, int on, int first); int coral_source_set_iomode_all(int off, int on, int first);
To set the default I/O mode of sources that have not yet been defined, use coral_set_iomode().
int coral_source_set_firmware(coral_source_t *src, const char *firmware); int coral_source_set_firmware_all(const char *firmware);
/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);
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);
coral_open()
or coral_open_all()
.
Addtionally, 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);
See also: coral_pkt_done.
int coral_close_all(void); int coral_close(coral_source_t *src);
crl_print_pkt.c
for a good example of using the packet API.
int coral_read_pkt_init(coral_source_t *src, coral_iface_t *iface, struct timeval *interval);
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()
implicitly
sorts packets by timestamp, the packet timestamps must be comparable.
If necessary,
coral_read_pkt_init()
will automatically enable the
CORAL_OPT_NORMALIZE_TIME
option to guarantee that the timestamps are comparable.
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);
coral_read_pkt_init()
.
If a packet filter has been set, only
packets that match the filter will be read.
Packets read are always sorted by time, regardless of the setting of the
CORAL_OPT_SORT_TIME
option.
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
.
}
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 ==
.
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.
NULL
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
.
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.
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);
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 approximately
*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 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)
extern volatile int coral_pkt_done;
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);
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()
).
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->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:
CORAL_
", the prefix, and the name;
e.g., CORAL_DLT_ATM_RFC1483
.
This function treats IPv6 extension headers as encapsulated protocols.
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,
the value of dst->protocol
after each successive call would be
CORAL_NETPROTO_IPv6
,
CORAL_IPPROTO_ROUTING
,
CORAL_IPPROTO_FRAGMENT
,
CORAL_IPPROTO_UDP
, and
CORAL_PROTO_UNKNOWN
,
respectively.
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().
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 is printed only if the URG flag is 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);
const char *coral_get_net_pkt(const coral_pkt_buffer_t *buffer, int *protocol);
int coral_add_pcap_filter(const char *expr)
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.
This function 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.
See also the section on -Cfilter in the command usage document.
const char *coral_get_pcap_filter(void)
NULL
if no filter expression has been set.
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);
These two 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().
These functions require including the pcap header <pcap.h>
.
See the pcap and tcpdump documentation for more information.
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); dump_packet(timestamp, buffer->buf); } 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 exceeded
NULL
with errno==EBADF
if sources are not ATM.
NULL
with other errno value for other errors
NULL
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);
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);
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)
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)
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)
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)
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);
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).
double coral_read_clock_double(const coral_iface_t *iface, const coral_timestamp_t *t); void coral_read_clock_sec_nsec(const coral_iface_t *iface, const coral_timestamp_t *t, time_t *sec, long *nsec); 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);
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-dependant 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_sec_nsec()
,
CORAL_TIMESTAMP_TO_TIMEVAL()
, and
CORAL_TIMESTAMP_TO_TIMESPEC()
splits the time into two integers, seconds and residual fractions of a second,
and writes them into *sec and *nsec,
*tv, or *ts, respectively.
double coral_cell_time_double(const coral_iface_t *iface, coral_atm_cell_t *cell);
coral_read_clock_double(iface, coral_cell_time(iface, cell))
.
coral_iface_t *coral_next_interface(const coral_iface_t *iface); coral_source_t *coral_next_source(const coral_source_t *src);
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);
const char *coral_source_get_filename(const coral_source_t *src);
NULL
if src is bad.
const char *coral_source_get_name(const coral_source_t *src);
NULL
if src is bad.
const char *coral_source_get_comment(const coral_source_t *src);
NULL
if src is bad or there is no comment.
int coral_get_source_count(void);
coral_source_t *coral_interface_get_src(const coral_iface_t *iface);
NULL
if iface is bad.
int coral_interface_get_type(const coral_iface_t *iface);
int coral_source_get_type(const coral_source_t *src);
int coral_interface_get_datalink(const coral_iface_t *iface);
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.
int coral_interface_get_physical(const coral_iface_t *iface);
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.
int coral_interface_get_bandwidth(const coral_iface_t *iface);
int coral_source_get_number(const coral_source_t *src); int coral_interface_get_number(const coral_iface_t *iface);
const struct timeval *coral_interface_get_capture_tv(const coral_iface_t *iface);
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);
coral_interface_get_capture_tv(iface)
.
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);
CORAL_prefix_name
constant (listed in the
Command Usage document)
indentifying 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".
coral_protocol_t coral_proto_id(const char *name);
coral_proto_{abbr,desc,str}()
.
int coral_proto_layer(coral_protocol_t protocol);
Macros:
get_vpvc_vp(vpvc)
get_vpvc_vc(vpvc)
set_vpvc_vp(vpvc, vp)
set_vpvc_vc(vpvc, vc)
vp_vc_to_vpvc(vp, vc)
Trace Writing
The writing API allows a programmer to copy data 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).
coral_writer_t *coral_write_open(const char *name);
".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.)
If the name is "-"
, data will be written to stdout.
Returns a pointer to a coral writer
for success, NULL
for failure.
The reccommended 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_fdopen(int fd);
Mixing CoralReef operations with other operations on descriptor fd may have unpredictable effects.
int coral_write_set_comment(coral_writer_t *writer, const char *comment); int coral_write_set_encoding(coral_writer_t *writer, const char *encoding);
int coral_write_init_all(coral_writer_t *writer); int coral_write_init_source(coral_writer_t *writer, coral_source_t *src);
int coral_write_init_interface(coral_writer_t *writer, coral_iface_t *iface);
int coral_write_cells(coral_writer_t *writer, const coral_iface_t *iface, const coral_atm_cell_t *cell, int count);
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);
coral_write_cells()
.
Returns 0 for success, -1 for failure.
int coral_write_close(coral_writer_t *writer);
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(); }
#include <pcap.h>
pcap_t *coral_iface_to_pcapp(coral_iface_t *iface); pcap_t *coral_iface_to_pcapp_raw(coral_iface_t *iface);
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);
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);
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);
pcap_dump()
.
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.
char *coral_filename(const char *str, char *dst, size_t len);
~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);
int coral_puts(const char *str);
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, ...);
printf(fmt, ...)
,
except that it prints to the CoralReef errfile instead of stdout,
and it is guaranteed to not modify errno
.
void coral_diag(level, (fmt, ...))
coral_printf(fmt, ...)
,
except that nothing will be printed if
level > verbosity
.
Returns void.
int coral_sendblk(coral_source_t *src, int ndesc);
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);
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;
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);
coral_fprint_pkt(iface, timestamp,
maxlayer, packet,
header, trailer)
is 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);
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_if_fmt_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 formated 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
subif into buf.
The size of buf should be at least
CORAL_FMT_SUBIF_LEN
.
The format depends on the data link type of iface:
void coral_dump(const coral_source_t *src); void coral_dump_all(void);
crl_info
.
void coral_stats(const coral_source_t *src); void coral_stats_all(void);
uint32_t coral_in_cksum_add(uint32_t psum, const void *data, int len); uint16_t coral_in_cksum_result(uint32_t psum);
psum
to 0
psum = 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 segment
coral_in_cksum_result(psum)
to get result.
int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_tIf these are not alrelady defined on your platform, <libcoral.h> will define them.
<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 */
interface
field may not correspond to
the number of the iface pointer returned by the
CoralReef reading functions.
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; };
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.
const coral_timestamp_t *coral_cell_time(iface, cell);
const union atm_hdr *coral_cell_header(iface, cell);
NULL
if iface is not an ATM interface.
const char *coral_cell_hec(iface, cell);
const char *coral_cell_payload(iface, cell);
size_t coral_cell_size(iface);
(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;
typedef struct { uint8_t cpcs_uu; /* CPCS user-to-user inidication */ 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.
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;