Libcoral operates on "sources". A libcoral source can be created from any of these filesystem entries:
The basic sequence of events for using libcoral to read a CoralReef source is:
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.
#include <stdio.h> #include <sys/param.h> #include <libcoral.h>CoralReef programs should link with
-lcoral.
Also, if libcoral was compiled with pcap support,
CoralReef programs should link with -lpcap.
int coral_config_arguments(int argc, char *argv[]);
-C 'config filename'" option
was given, this function will also process that config file.
A CoralReef source is created from each filename argument.
If an option syntax error is encountered, this function prints a usage message.
If other arguments are desired, use coral_config_options() instead;
if other options are desired, use coral_config_command().
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.
int coral_config_options(int argc, char *argv[], const char *argmsg);
-C 'config filename'" option
was given, this function will also process that config file.
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], argmsg).
If argmsg is NULL, this
function assumes that no arguments other than coral options are allowed,
and returns -1 if other arguments are found.
If argmsg is not NULL, other arguments (but not other options)
are allowed.
If other options are desired, use coral_config_command() instead.
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.
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
"[<argument>]"
"[-b] [-f <string>]"
"[-b] [-f <string>] [<argument>]"
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, bflag = 0;
char *string = NULL;
extern char *optarg;
extern int optind;
while ((opt = getopt(argc, argv, "C:bf:")) != -1) {
switch (opt) {
case 'C':
if (coral_config_command(optarg) < 0)
exit(-1);
break;
case 'b':
bflag = 1;
break;
case 'f':
string = optarg;
break;
default:
coral_usage(argv[0], "[-b] [-f <string>]");
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:
Usage: app [-C <coral_command>]... [-b] [-f <string>]
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_read_cell_all() read cells in temporal order.
This option may only be used on file sources, not device sources.
coral_read_pkt() and coral_read_pkts()
to handle partial packets.
int coral_set_iomode(int off, int on, int first, int fixed);
The I/O mode flags:
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 cells in the trace will still be read. In a future release, the read functions will filter trace files according to the I/O mode (or generate an error if that is not possible).
On point cards, coralreef supports CORAL_RX, CORAL_RX_IDLE, CORAL_RX_OAM, CORAL_RX_LAST, CORAL_RX_USER_ALL; and a first value of 0, 1, 2, or 3. Echoing is is always enabled, no matter how CORAL_RX_ECHO is set.
On fatm cards, coralreef supports CORAL_TX, CORAL_RX, CORAL_RX_LAST, CORAL_RX_USER_ALL, CORAL_RX_ECHO; and a first value of 0, 1, 2, or 3.
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
(e.g., by coral_set_errfilename(),
but not by coral_set_errfile()).
If file or filename is NULL, stderr 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_comment(const char *comment); const char *coral_get_comment(void);
coral_writer_set_comment().
int coral_set_duration(long duration); long coral_get_duration(void); int coral_set_interval(long interval); long coral_get_interval(void);
If the interval value is greater than 0, it will automatically be used by the
cell reading functions.
You may use the interval value with
packet reading functions by passing
the result of coral_get_interval() in as a parameter.
Typically, you should use the duration value if you want to set the length of time that the application will run; and use the interval value if you want to do something periodically during the application run (e.g., by passing it as the interval parameter to coral_read_pkt_init() or coral_read_cell_i()).
coral_source_t *coral_new_source(const char *filename);
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);
int coral_source_set_firmware(coral_source_t *src, const char *firmware); int coral_source_set_firmware_all(const char *firmware);
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.
Returns the number of interfaces opened if successful, or -1 for failure.
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.
These functions currently have no effect on tracefile sources,
but should be called anyway for consistency and future compatibility.
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);
int coral_read_pkt_init(coral_source_t *src, coral_iface_t *iface,
int 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.
Packets can be read from multiple OCx sources, or a single pcap source, but
not from multiple pcap sources or a mixture of pcap and OCx sources.
If iface belongs to a source with multiple interfaces, data
from the other interfaces 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 number of seconds coral_read_pkt()
will wait between returning statistical information (measured against packet
timestamps).
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().
pkt_result and interval_result are pointers to structures
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:
pkt_result->packet == NULL &&
interval_result->stats == NULL
interval_result->begin.
(interval_result->end is not valid.)
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);
and pkt_result->trailer will point to a
coral_pkt_buffer_t
containing the AAL5 trailer (in network byte order), if available.
On other types of interfaces, pkt_result->header
and pkt_result->trailer will be NULL.
pkt_result->packet == NULL &&
interval_result->stats != NULL
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 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
interval.
The interval includes all packets in each
internal buffer for which the first packet of the internal buffer falls within
interval seconds of the beginning of the interval.
In version 3.1, internal buffering might have made an actual interval quite a
bit longer than interval if there was not much traffic on the
monitored link; this is no longer true in version 3.2.
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;
if there is no matching proto configuration rule, the protocol defaults to
CORAL_DLT_ATM_RFC1483.
If coral_cell_block_hook points to a user-defined function, it will be called when a new block of ATM cells is read.
For EOF or a stopped device, coral_read_pkt() returns NULL with
errno == 0.
For error, coral_read_pkt() returns NULL with
errno set to indicate the error.
int coral_read_pkts(coral_source_t *src, coral_iface_t *iface, pkt_handler pkthandler, pre_interval_handler preinthandler, post_interval_handler postinthandler, long interval, void *userdata);
coral_read_pkt_init().
coral_read_pkts() repeatedly reads link level packets
until coral_pkt_done != 0,
or (if input is a trace file) end of file is reached.
pkthandler is a pointer to a function that will be called for each packet received. Normally, even truncated packets are handled, but only complete packets will be handled if the CORAL_OPT_PARTIAL_PKT option is disabled (but truncated packets are always counted by the truncated field of coral_pkt_stats_t).
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. The beginning of an interval is always aligned to a multiple of interval. The interval includes all packets in each internal buffer for which the first packet of the internal buffer falls within interval seconds of the beginning of the interval. Because of internal buffering, a interval may actually be quite a bit longer than interval if there is not much traffic on the monitored link. preinthandler and postinthandler are not called if they are NULL or if interval <= 0.
userdata 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.
typedef void (*pkt_handler)(coral_iface_t *iface, coral_timestamp_t *timestamp,
void *userdata, coral_pkt_buffer_t *packet, coral_pkt_buffer_t *header,
coral_pkt_buffer_t *trailer);
coral_read_pkts()
reads a packet.
Parameters:
coral_read_pkts().
typedef int (*pre_interval_handler)(coral_iface_t *iface, struct timeval *begin, void *userdata); typedef int (*post_interval_handler)(coral_iface_t *iface, struct timeval *begin, void *userdata, coral_pkt_stats_t *stats);
pre_interval_handler and post_interval_handler
are called before and after (respectively) each interval of
coral_read_pkts().
Parameters:
coral_read_pkts()
extern volatile int coral_pkt_done;
See also: coral_stop_all().
extern int (*coral_pkt_atm_hook)(coral_iface_t *iface, coral_pkt_buffer_t *packet, coral_atm_cell_t *cell);
coral_pkt_atm_hook is not NULL, the user defined 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 processed 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
pkt_handler of coral_read_pkts().
The parameters are:
coral_iface_t *iface
coral_pkt_buffer_t *packet
coral_pkt_buffer_t parameter
(e.g., coral_get_payload()).
coral_atm_cell_t *cell
coral_pkt_atm_hook is NULL.
int coral_get_payload(const coral_pkt_buffer_t *src, coral_pkt_buffer_t *dst);
pkt_handler()).
coral_get_payload() skips past the lower level (outer) protocol
encapsulation in src and fills in dst with information
about the payload of src.
dst->protocol will contain
CORAL_PROTO_UNKNOWN if coral_get_payload()
understands the src protocol but does
not recognize the protocol of the payload.
coral_get_payload() returns 0 if it successfully parsed
the src protocol information, or -1 if
libcoral does not know how to parse the protocol of src,
there is an error in the src packet,
the protocol information in src buffer was truncated,
or src->protocol is unknown.
The recognized protocols are listed in the
Command Usage document.
Protocol identifiers are formed by concatenating "CORAL_", the prefix, and the
name; e.g., CORAL_DLT_ATM_RFC1483.
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 human-readable information about the lower level protocol
into buf, which has length len.
Returns the length of the string written into buf if successful,
or -1 if vsnprintf() is not available on your system
and buf is not NULL,
or for any of the errors listed in the documentation for
coral_get_payload().
int coral_get_payload_by_proto(const coral_pkt_buffer_t *src,
coral_pkt_buffer_t *dst, int proto);
int coral_get_payload_by_layer(const coral_pkt_buffer_t *src,
coral_pkt_buffer_t *dst, int layer);
*dst.
If there are packets a multiple layers that match, the outermost matching packet
is selected.
Returns 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().
char *coral_get_net_pkt(const coral_pkt_buffer_t *buffer, int *protocol);
static int handle_packet(coral_iface_t *iface, 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, handle_packet, NULL, NULL, 0, &count);
printf("received %ld packets.\n", count);
...
}
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. All structures will be in network byte order. (In version 3.0, cells read from FATM devices had ATM headers in little endian order.)
If timeout is NULL (or not available), these functions will wait until data is 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 points to a user-defined function, it will be called when a new block of ATM cells is read by any of the cell reading functions.
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 set by previous calls to any reading functions on the same set of sources.
errno==0 for EOF or stopped device
(If the EOF occured someplace other than a block boundary, a warning
is printed to the coral errfile.)
errno==EAGAIN if timeout is exceeded
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_all() reads cells in the most
efficient order (i.e., block order);
but if the CORAL_OPT_SORT_TIME
option is set, it will read them
in time-sorted order (interleaving cells from different blocks).
This assumes that all interfaces were started simultaneously
when the trace was made.
If the CORAL_OPT_SORT_TIME is set,
timeout is ignored (it is always treated as NULL).
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, int 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, int interval);
coral_read_cell() and coral_read_cell_all(),
except that there is no timeout and they support intervals.
If
interval > 0, then
the CORAL_OPT_SORT_TIME
option is automatically enabled, 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
filled in with the boundaries of the interval.
When EOF is reached, the final partial interval is returned, and the
next call will return NULL.
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);
*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).
void (*coral_cell_block_hook)(const coral_iface_t *iface, coral_blk_info_t *binfo)
coral_cell_block_hook points to a user-defined function,
it 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_cell_to_pkt(const coral_iface_t *iface, coral_atm_cell_t *cell,
coral_pkt_buffer_t *pkt)
coral_cell_to_pkt fills in 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.
const char *coral_file_version(const coral_source_t *src)
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, long *sec, long *nsec);
coral_read_clock_sec_nsec()
splits the time into seconds and nanoseconds integer components,
and writes them into *sec and *nsec, respectively.
coral_read_clock_double() returns the time
as floating point number of seconds (to the nearest nanosecond).
Note that some precision may be lost, especially when the time is normalized.
These functions automatically correct the case in which the FORE card doesn't increment the software clock because it misses a hardware clock wrap.
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_TIMESTAMP_TO_TIMESPEC(const coral_iface_t *iface, const coral_timestamp_t *t, struct timespec *tspec) CORAL_TIMESTAMP_TO_TIMEVAL(const coral_iface_t *iface, const coral_timestamp_t *t, struct timeval *tval)
coral_iface_t *coral_next_interface(const coral_iface_t *iface); coral_source_t *coral_next_source(const coral_source_t *src);
coral_source_t *src = NULL;
while ((src = coral_next_source(iface))) {
coral_dump(src);
}
const char *coral_source_get_filename(const coral_source_t *src);
const char *coral_source_get_comment(const coral_source_t *src);
int coral_get_source_count(void);
coral_source_t *coral_interface_get_src(const coral_iface_t *iface);
int coral_source_get_type(const coral_source_t *src);
int coral_interface_get_type(const coral_iface_t *iface);
int coral_interface_get_datalink(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);
time_t coral_interface_get_capturetime(const coral_iface_t *iface);
const char *coral_proto_abbr(int protocol); const char *coral_proto_desc(int protocol); const char *coral_proto_str(int protocol);
CORAL_prefix_name
constant (listed in the
Command Usage document)
indentifying a data link layer protocol.
These functions return a pointer to a string describing protocol:
coral_proto_abbr, a short name
(listed in the
Command Usage document);
coral_proto_desc, a long description, or NULL;
coral_proto_str, a long description, or "unknown N".
int coral_proto_id(const char *name);
CORAL_prefix_name 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}().
int coral_proto_layer(int 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" and CoralReef was compiled with libz,
the file will be gzipped.
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".
Note: to ensure that all data are written, you must use
coral_write_close(),
do not rely on program exit to close the trace.
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);
void stopper(int sig)
{
stop = 1; /* must use a flag, because coral_stop() is not async-safe */
}
int main(int argc, char *argv[]) {
coral_writer_t *writer;
coral_iface_t *iface;
coral_atm_cell_t *blk;
coral_blk_info_t *binfo;
int stop = 0;
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);
signal(SIGALRM, stopper);
alarm(coral_get_duration());
if (coral_start_all() < 0)
exit(5);
while (1) {
if (stop) {
coral_stop_all();
stop = 0;
}
iface = coral_read_block_all(&binfo, &blk, NULL);
if (!iface) {
if (errno == EINTR) continue;
break;
}
if (coral_write_block(writer, iface, binfo, blk) < 0)
exit(6);
}
coral_close_all();
coral_write_close(writer);
}
#include <pcap.h> #include <pcap-int.h>
int coral_iface_to_pcap(const coral_iface_t *iface, pcap_t *pcap);
int coral_pkt_to_pcap(const coral_iface_t *iface, const coral_timestamp_t *timestamp,
const coral_pkt_buffer_t *pkt, struct pcap_pkthdr *hdr);
pcap_t pcap; struct pcap_pkthdr pcap_hdr; /* ... */ if (coral_iface_to_pcap(iface, &pcap) < 0) /* handle error */; pcap_dumper = pcap_dump_open(&pcap, filename); /* ... */ iface = coral_read_pkt(&pkt_result, &interval_result); if (!iface) /* handle error */; coral_pkt_to_pcap(iface, pkt_result.timestamp, pkt_result.packet, &pcap_hdr); pcap_dump(pcap_dumper, &pcap_hdr, pkt_result.packet->buf);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, the resulting pcap file will be corrupt.
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_print_data(int indent, const u_char *data, size_t len);
void coral_print_cell(int indent, const coral_iface_t *iface,
const coral_atm_cell_t *cell);
void coral_print_pkt(coral_iface_t *iface, coral_timestamp_t *timestamp,
void *layerp, coral_pkt_buffer_t *packet, coral_pkt_buffer_t *header,
coral_pkt_buffer_t *trailer);
*(int*)layerp
expanded by fields, and the payload in hex.
coral_print_pkt() is suitable for use as a
pkt_handler for
coral_read_pkts().
void coral_dump(const coral_source_t *src); void coral_dump_all(void);
void coral_stats(const coral_source_t *src); void coral_stats_all(void);
unsigned long coral_in_cksum_add(unsigned long psum, const void *data,
int len);
unsigned short coral_in_cksum_result(unsigned long 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.
coral_source_t coral_iface_t coral_writer_t coral_timestamp_t
typedef struct {
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 */
} coral_blk_info_t;
Note that the 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 {
u_int gfc : 4; /* generic flow control */
u_int vpvc : 24; /* virtual path + virtual circuit indicators */
u_int oam_rm : 1; /* PTI: OAM/RM indicator (ie, not user data) */
u_int congestion : 1; /* PTI: we don't use this */
u_int sdu_type : 1; /* PTI: in AAL5, this marks end of SAR-SDU */
u_int clp : 1; /* cell loss priority */
} h;
u_int ui;
};
The correct way to access the fields of a cell is with the new cell accessor functions.
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);
(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 structure below is documented 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 {
u_char cpcs_uu; /* CPCS user-to-user inidication */
u_char cpi; /* common part indicator */
u_short length; /* length of CPCS PDU payload */
u_int crc; /* cyclic redundancy check of CPCS PDU */
} aal5_trailer_t;
typedef struct {
u_char llc_dsap;
u_char llc_ssap;
u_char llc_cntl;
u_char snap_org[3];
u_short snap_type;
} llcsnap_t;
typedef struct {
int caplen; /* length of data actually captured in buf */
int totlen; /* total length of pkt (negative if unknown) */
char *buf; /* data (aligned to a multiple of 4 bytes) */
int protocol; /* protocol */
} coral_pkt_buffer_t;
typedef struct {
unsigned long pkts_recv; /* packets received */
unsigned long pkts_drop; /* packets dropped */
unsigned long truncated; /* packets truncated by insufficient capture */
unsigned long driver_corrupt; /* cell looks bad from the capture device */
unsigned long too_many_vpvc; /* too many simultaneous vpvc pairs */
unsigned long buffer_overflow; /* AAL5 cell stream > MAX_PACKET_SIZE */
unsigned long aal5_trailer; /* AAL5 trailer had bad length
probably caused by driver_corrupt drops */
unsigned long ok_packet;
} coral_pkt_stats_t;
Note that the cells_recv and cells_drop fields
present in version 3.1 have been removed, for two reasons: they were ATM
specific, and they required that intervals be aligned with blocks of ATM
cells. ATM block data may now be obtained via
coral_cell_block_hook.
typedef struct {
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) */
} coral_pkt_result_t;
typedef struct {
struct timeval begin; /* beginning of interval */
struct timeval end; /* end of interval */
coral_pkt_stats_t *stats; /* statistics for interval */
} coral_interval_result_t;