Coral.pm - a Perl API for CoralReef

Introduction

Coral.pm provides a Perl API for reading network interface devices and several different trace file formats, and for writing trace files. It is mostly a wrapper for calls to libcoral, with some additional Perl-centric structures when appropriate.

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 Coral.pm has this basic structure:

  configure Coral.pm and one or more sources
  open sources
  start sources
  while (read cell or packet != undef) {
      process the data we just read
      if (stop condition occurs) {
	  stop sources
      }
  }
  close sources

All identifiers defined in this document are in the Coral namespace, and are not exportable. Therefore, all methods must be fully qualified, e.g.: Coral::quick_start().

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.

Note on 'Prototypes'

The types and prototypes listed in the class definitions and function parameters vary somewhat from standard Perl form. When possible, instead of merely calling types 'SCALAR' or 'LIST', additional information has been given as to the type of the parameter. Optional parameters are followed by "=" and their default value. Examples of types:
BOOL
A Boolean (true/false) value. Usually 1 or 0.
STR
A string value.
NUM
A number (integer or floating point) value.
LIST REF
A reference to a list.
STR REF
A reference to a string.
SomeClass
A blessed reference to one of the classes used by Coral.
SCALAR
An opaque object, never accessed directly by the user. Usually returned by a function call. For example, the timestamp in the Cell or Pkt_buffer classes, which is read by the read_clock functions, or a source or interface returned by the next_source or next_interface functions.
Also, the 'FILEHANDLE' types must be attached to an actual stdio FILE.

The API

Quick Start

quick_start(BOOL time_sort = 0, BOOL partial_pkt = 1, NUM api = API_PKT);

This Perl-only function does the configuration and startup for most common cases of CRL use. If finer control is needed, use the command line configuration and global configuration functions below. If time_sort equals 1, cells/packets will be sorted, otherwise they will not. If partial_pkt equals 0, then truncated packets are discarded by read_pkt(), otherwise they are accepted. Api allows the user to set the libcoral API being used; the default is API_PKT.

To limit the number of sources that will be allowed, call set_max_sources() before calling this function.

This function returns nothing. If any fatal errors are encountered, it exits.

The code consists of:

sub quick_start {
    my ($time_sort, $partial_pkt, $api) = @_;

    if (defined $time_sort and $time_sort != 0) {
	if (Coral::set_options(0, $Coral::OPT_SORT_TIME) < 0) {
	    Coral::puts("Warning: could not set time-sorting option!");
	}
    } elsif (Coral::set_options($Coral::OPT_SORT_TIME, 0) < 0) {
	Coral::puts("Warning: could not unset time-sorting option!");
    }

    if (defined $partial_pkt and $partial_pkt == 0) {
	if (Coral::set_options($Coral::OPT_PARTIAL_PKT, 0) < 0) {
	    Coral::puts("Warning: could not unset partial packeting option!");
	}
    } elsif (Coral::set_options(0, $Coral::OPT_PARTIAL_PKT) < 0) {
	Coral::puts("Warning: could not set partial packeting option!");
    }

    if (defined $api) {
	if (Coral::set_api($api) < 0) {
	    Coral::puts("Warning: could not specify api!");
	}
    } elsif (Coral::set_api($Coral::API_PKT) < 0) {
	Coral::puts("Warning: could not specify packet api!");
    }

    if (Coral::config_arguments(scalar(@ARGV), \@ARGV) < 0) {
	Coral::puts("Error: could not parse command-line options!");
	exit(1);
    }
    if (Coral::open_all() <= 0) { # no openable sources is considered an error
	Coral::puts("Error: could not open any sources!");
	exit(1);
    }
    if (Coral::start_all() < 0) {
	Coral::puts("Error: could not start any sources!");
	exit(1);
    }
}

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 open() or open_all().

You should call set_api() before calling these functions to enable certain configuration commands. Also, you should set the defaults for configurable values with the 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 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 usage() message, and the config functions will not allow it to be changed on the command line.

config_arguments(NUM argc, LIST REF argv);

This function processes "-C" options and sourcename arguments contained in argv. Argv is a reference to a list 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 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 config_options() instead and parse the arguments yourself; if other options are desired, parse the options and arguments yourself and call 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 set_max_sources() before calling this function.

Sample call: $nxt_idx = config_options(scalar(@ARGV), \@ARGV, "<outputfile>");

config_options(NUM argc, LIST REF argv, STR argmsg);

This function is like config_arguments(), except it processes only the options, not the non-option arguments. If argmsg is undef, 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. 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 usage($0, argmsg). If other options are desired, use config_command() instead. Returns a non-negative integer for success, -1 for failure.

Sample call: $nxt_idx = config_options(scalar(@ARGV), \@ARGV, "<outputfile>");

config_command(STR command, STR filename, NUM linenum);

Processes a config command. This function should be used instead of config_options() or 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. Filename and linenum are printed in error messages; pass undef and 0 to have them not printed. Returns 0 for success, -1 for failure.

config_file(STR filename);

Process CoralReef commands in file filename. This is not usually needed if config_arguments(), config_options(), or config_command() is used.

usage(STR appname, STR argmsg = undef);

Prints a message describing the command line syntax of a CoralReef application named appname. If argmsg is not undef, it is appended to the syntax line. This is followed by descriptions of the CoralReef (-C) command line options.

Some example values for argmsg:

for an application that takes CoralReef options and no arguments:
undef
for an application that takes CoralReef options and an optional argument
"[<argument>]"
for an application that takes -f, -bN, and CoralReef options, and one or more source arguments:
"[-f] [-b<N>] <source>..."

Examples

If only Coral options and filename arguments are needed, this simple code will do:
	Coral::quick_start(0); # or 1 for time-sorting
    
followed by the read_cell routines. If other options are desired, you must parse the options and arguments yourself. If a bad option is given, this code will print a message like this to stderr, followed by descriptions of the Coral commands:
      Usage: app [-C <command>]... <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 set functions can be called before the config functions to set default values that can be overridden on the command line or config file, and will be displayed in the usage message. If the integer configuration values are set to a negative value, they will not be displayed in the usage message. The set functions can also be called after the config functions so their values can't be overridden. They must not be called after sources are opened. The set functions return 0 if successful, or -1 for failure; the get functions return the value of the requested datum.

config_defaults();

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.

set_api(NUM api);

The api parameter to set_api() must be API_CELL, or API_PKT, optionally bitwise ORed with 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. Coral.pm 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
API_CELL cells blocks deny
API_PKT packets filter deny 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 write or a rotating output file will be used:

API allowed configuration commands allowed functions
API_WRITE gzip set_gzip()

Example: set_api(API_PKT | API_WRITE);

set_max_sources(NUM n);
get_max_sources();

set_max_sources() sets the maximum number of allowed Coral sources to n. It should be called before config_arguments(), config_options(), config_command(), and new_source() to restrict them. It returns 0 if successful, or -1 if n is negative or greater than 16. get_max_sources() returns the maximum number of allowed Coral sources. The default max_sources value is 16.

set_options(NUM off, NUM on);
get_options();

set_options() disables the options in the bitmask off and enables the options in the bitmask on. get_options() returns a bitmask of currently enabled options. The options are:

OPT_SORT_TIME (default: off, unless quick_start(1) is used.)
Makes read_cell_all() and 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 OPT_NORMALIZE_TIME option is on. If none of these conditions is true, libcoral will automatically enable the OPT_NORMALIZE_TIME option. If your application requires time sorting, set this option before the command-line config functions so "sort" will not appear in the usage message.
OPT_ALIGNINT (default: off)
Aligns end of first interval to a multiple of the interval length.
OPT_PARTIAL_PKT (default: on)
Allows read_pkt() to handle partial packets.
OPT_FATM_RAW_TIME (default: off)
Do not attempt to automatically correct the delayed firmware clock increment when the hardware clock wraps in the fatm card or skip cells prior to a clock reset in the first block. This can be used to improve performance if cell/packet timestamps will not be needed.
OPT_POINT_RAW_TIME (default: off)
Do not attempt to automatically skip cells prior to a clock reset in the first block. This can be used to improve performance if cell/packet timestamps will not be needed.
OPT_RAW_TIME
Equivalent to (OPT_FATM_RAW_TIME | OPT_POINT_RAW_TIME).
OPT_NORMALIZE_TIME (default: on)
Make the result of the read_clock relative to the unix epoch (1970-01-01 00:00:00 UTC); otherwise, the result will have some interface-dependent epoch. Normalizing is necessary when comparing times from multiple interfaces (this includes using 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:
fatm
time of reset (e.g., by start_all());
point
time of reset (e.g., by start_all());
dag
the unix epoch (of the CPU used to do the capture)
pcap
the unix epoch (of the CPU used to do the capture)
tsh
either the unix epoch or the time of reset, depending on the original source of data (libcoral can identify the epoch automatically)
Traces from interfaces that don't natively use the unix epoch can only be normalized if the capture time was recorded in the trace. NLANR and MCI .crl traces do not contain capture time, although their filenames sometimes do, and CoralReef can use that; .crl traces made with CoralReef prior to 3.2.1 contain capture time only to the nearest second. Traces in .tsh format do not explicitly contain the capture time, but if the data timestamps are relative to the unix epoch, libcoral will use the first timestamp as the capture time; otherwise, libcoral will infer a capture time from the filename if possible.
OPT_NO_FILTER (default: off)
Do not allow a pcap filter to be set by the config functions. This is useful for applications that need to define their own filters.
OPT_IP_CKSUM (default: off)
Tells fmt_get_payload() to print and verify IP checksums.
OPT_IP_EXTHDR (default: off)
Tells get_payload() to not skip IP extension headers.
OPT_IGNORE_TIME_ERR (default: off)
By default, libcoral reading functions return an error when they encounter a timestamp error they can not correct in a source. With this option enabled, libcoral will continue reading normally, but beware that intervals and duration may not work correctly.
OPT_NO_AUTOROTATE_ERRFILE (default: off)
By default, an error file whose name contains "%" is rotated at the beginning of intervals. With this option turned on, automatic rotation is disabled.

set_iomode(NUM off, NUM on, NUM first = -1, BOOL fixed = 0);

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 source_set_iomode().)

The arguments to this function are:

off
bitmask of I/O mode flags to disable.
on
bitmask of I/O mode flags to enable.
first (defaults to -1)
specifies how many bytes to capture from each PDU (layer 2 packet/frame). If this parameter is negative, the configured value will be unchanged. For ATM interfaces, first will be rounded up to a multiple of ATM cell payload size (48 bytes). (In versions prior to 3.2, first was interpreted as cells instead of bytes on ATM interfaces.)
fixed (defaults to false)
flag that prevents user from modifying the iomode via the command line or config file (this should be used before the config functions, in applications with a non-configurable iomode).

The I/O mode flags are:

flag equivalent CLI iomode description
TX tx allow transmitting (not implemented)
RX rx allow receiving
RX_IDLE idle read all cells, including ATM idle cells
RX_OAM ctrl read ATM OAM/RM cells
RX_LAST last read last cell of each ATM AAL5 user PDU (packet)
RX_USER_ALL user read all bytes of each packet or frame
RX_ECHO echo retransmit received cells on devices which support it (always enabled on POINT cards)
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 RX_USER_ALL flag, and setting the 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 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.

get_iomode();

Return the default iomode as set by set_iomode() or command line options. The iomode is returned in the form (flags, first_n).

set_errfilename(STR filename);

set_errfilename() sets the destination for future libcoral error and warning messages. filename is the name of a file that will be opened by Coral.pm. Any previously set error file will be closed only if it was set by name other than "-". If filename is undef, stderr will be used. If filename is "-", stdout will be used. 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 rf_open. Unlike normal rotfiles, a rotating error file is always writable by Coral.pm; it does not need to be started. A rotatable error file will rotate automatically at the beginning of each interval of read_pkt or read_pkts, unless then OPT_NO_AUTOROTATE_ERRFILE option is set. In any case, rotate_errfile can be called to rotate the error file explicitly. If rotation fails, the error file resets to stderr.

set_verbosity(NUM verbosity);
get_verbosity();

Set or get the verbosity level of Coral.pm. If verbosity==0, only errors are printed; if verbosity==1 errors and warnings are printed. The default verbosity is 1. To completely disable coral messages, set the verbosity to -1.

set_max_pkts(NUM n);
set_max_cells(NUM n);
set_max_blks(NUM n);
get_max_pkts();
get_max_cells();
get_max_blks();

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 cell

set_skip_pkts(NUM n);
get_skip_pkts();

Get or set the number of packets that will be discarded by the packet reading API.

set_comment(STR comment);
get_comment();

Set or get the default comment that will be written in the file header by the write functions. The default comment may be overridden by the comment parameter of write_open().

set_duration(NUM duration);
get_duration();

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 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 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.

set_interval(LIST REF interval);
get_interval();

Set or get the interval value. If the interval has not yet been set, get_interval() returns (-1, -1, -1); otherwise, it returns (0, sec, usec), where sec and usec are the seconds and microseconds, respectively of a 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 get_interval() in as a parameter to read_pkt_init() or 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 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 config functions.

Libcoral does not use SIGALRM to implement interval.

See also: OPT_ALIGNINT.

set_dropinterval(LIST REF dropinterval);
get_dropinterval();

Set or get the dropinterval value. The default dropinterval value is { 0, 0 }. If the dropinterval has been set to a negative value, get_dropinterval() returns (-1, -1, -1); otherwise, it returns (0, sec, usec), where sec and usec are the seconds and microseconds, respectively of a nonnegative interval value.

A positive value for dropinterval is used as the period with which 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 config functions.

The dropinterval is independent of the normal interval and OPT_ALIGNINT.

set_mintime(LIST REF t);
get_mintime();
set_maxtime(LIST REF t);
get_maxtime();

Set or get the mintime or maxtime value. If the desired value has not yet been set, the get functions return (-1, -1, -1); otherwise, they return (0, sec, usec), where sec and usec are the seconds and microseconds, respectively of a nonnegative time 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 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 config functions.

set_gzip(STR mode);

If mode is undef, write_open() will not gzip files unless they end in ".gz". If mode is "", write_open() will gzip files with the default parameters (compression level 1). If mode is a non-empty string, write_open() will append it to the "wb" mode when calling gzopen(); see the zlib documentation for details.

Source Configuration

These functions define and configure sources. They may only be called before opening sources.
new_source(STR sourcename);

Create a new coral source from sourcename. Sources are described in the Command usage document. Returns source pointer if successful, or undef for failure. This function is useful for creating a source directly from the program (instead of through command line and config file with the config functions).

new_fsource(FILEHANDLE file, STR sourcename = undef);

Like new_source, except that it uses the already-open file handle file instead of a filename. If sourcename is not undef, open() will examine it for a prefix or suffix to determine how to interpret the data read from file; otherwise, open() will assume data from file contains a CoralReef (crl) trace. This function is useful for creating a source directly from a file handle in the program; for example, a socket connected to another process that used write_fopen().

Mixing CoralReef operations with other operations on handle file may have unpredictable effects.

source_set_iomode(SCALAR src, NUM off, NUM on, NUM first = -1);
source_set_iomode_all(NUM off, NUM on, NUM first = -1);

These functions modify the I/O mode of the indicated already defined sources. The off, on, and first arguments are identical to those of 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 set_iomode().

source_get_iomode(SCALAR src);
iface_get_iomode(SCALAR 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. The iomode is returned in the form (flags, first_n).

coral_format_iomode(LIST REF iomode);

Returns a human-readable representation of iomode. iomode is a reference to a two-element array, such as [$flags, $first_n], where $flags and $first_n are returned by source_get_iomode or iface_get_iomode.

source_set_firmware(SCALAR src, STR firmware);
source_set_firmware_all(STR 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.

Opening

Sources must be opened and started before they can be read. When they are no longer needed, they may be stopped and should be closed. Note that failing to close a DAG card source may leave it in an unusable state (/proc/dag will report the device is "Busy"); the card must be re-initialized before CoralReef can read from it again.
open(SCALAR src);
open_all();

Open the indicated coral sources that have been created by config_arguments(), config_options(), config_command(), and 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.

start(SCALAR src);
start_all();

Start capture on interface(s) of the indicated coral sources which have been opened with open() or open_all(). Additionally, 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.)

stop_all();
stop(SCALAR 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).

close_all();
close(SCALAR src);

Close all interfaces of the indicated sources, after flushing any partially filled blocks. Returns 0 for success, -1 for failure.

Packet Reading

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.

Note that the data in packets returned by the packet API is not guaranteed to have any particular alignment.

Single packet reading

read_pkt_init(SCALAR src, SCALAR iface, LIST REF interval = undef);

Prepare to read packets from an open src or iface with read_pkt(). If iface is not undef, packets will be read from iface; otherwise, if src is not undef, 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 read_pkt_init() invalidates any sources that were previously initialized for packet reading. Interval is the amount of time read_pkt() will wait between returning statistical information (measured against packet timestamps). To set the interval, give read_pkt_init() a reference to a 2-element array representing the seconds and microseconds of the interval, such as [100, 0], which might come from get_interval(). Interval defaults to undef, which disables interval handling. read_pkt_init() returns 0 if successful, or -1 if an error occurs.

Because read_pkt() must be able to compare timestamps, read_pkt_init() will automatically enable the OPT_NORMALIZE_TIME option if necessary.

read_pkt_init() returns 0 if successful, or -1 if an error occurs.

read_pkt(Pkt_result pkt_result, Interval_result interval_result = undef);

Read a packet from one of the interfaces which have been initialized with 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 OPT_SORT_TIME option was set when read_pkt_init() is called (prior to version 3.6, packets were always sorted by time, regardless of the setting of the 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 OPT_PARTIAL_PKT option is turned off, only complete packets will be read (but truncated packets are always counted by the truncated field of Pkt_stats).

pkt_result and interval_result are references to objects created by the user that will be filled in by the call. For success, read_pkt() returns the interface which was read, and the contents of the objects indicate what happened:

if (defined pkt_result->packet) {
A packet was read; information about the packet is contained in pkt_result.
pkt_result->packet will reference a Pkt_buffer containing the link layer (LLC/SNAP, ethernet, etc) PDU. On ATM interfaces, pkt_result->header will reference a Pkt_buffer 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 reference a Pkt_buffer 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 undef, and pkt_result->subiface will be 0.
} elsif (not defined interval_result->stats) {
An interval has begun at time interval_result->begin. (interval_result->end is not valid.)
} else {
The interval begun at time 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 OPT_SORT_TIME option is not enabled.
}

If the interval specified in read_pkt_init() was undef or 0, interval_result may be omitted or undef, and read_pkt() will never return with pkt_result->packet == undef. 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 . 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 NETPROTO_IPv4, and IP options are always zero; the protocol of an invalid packet is PROTO_UNKNOWN. Packets read from raw IP sources (i.e., pcap DLT_RAW) will have their protocol set to NETPROTO_IPv4 or NETPROTO_IPv6 if they contain at least 1 byte of data; otherwise, they will have protocol NETPROTO_RAW_IP.

To indicate EOF, a stopped device, or expired duration, read_pkt() returns undef with $! == 0. For an error, read_pkt() returns undef with $! 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 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, 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:

{
    $pkt_result = new Coral::Pkt_result;
    $interval_result = new Coral::Interval_result;
    Coral::read_pkt_init(undef, undef, $interval);
    while (1) {
	$iface = Coral::read_pkt($pkt_result, $interval_result);
	if (!iface) {
	    # error
	    last;
	}
	if (defined $pkt_result->packet) {
	    # got packet
	    ...
        } elsif (not defined $interval_result->stats) {
	    # beginning of interval
	    ...
	} else {
	    # end of interval
	    ...
	}
    }
}

Other packet reading features

get_payload(Pkt_buffer src, Pkt_buffer dst);

src is a reference to a Pkt_buffer containing a datagram or packet (e.g., packet_result->packet from read_pkt()) with src->caplen > 0. Dst is also a reference to a Pkt_buffer, but is created by the user, e.g.: "$argument = new Pkt_buffer;". get_payload() skips past the lower level (outer) protocol encapsulation in src and fills in dst with information about the payload of src (see Pkt_buffer). If get_payload() understands the src protocol but does not recognize the protocol of the payload, dst->protocol will contain PROTO_UNKNOWN or some other undefined value.

get_payload() returns 0 if it successfully parsed the src protocol information, or one of the following negative error codes:

ENOPROTO
libcoral can not parse the protocol indicated by src->protocol
ELENGTH
protocol information was truncated
ESYNTAX
packet data are inconsistent with protocol
ERROR
other error

A return value of 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 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 the prefix and the name, in the Coral namespace; e.g., DLT_ETHER.

By default, the IPv6 extension headers HOPOPTS, ROUTING, FRAGMENT, and DSTOPTS are skipped; but if the 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 get_payload() with that packet as src, and then repeatedly with the dst of the previous call as the src of the next, with OPT_IP_EXTHDR off, the value of dst->protocol after each successive call would be NETPROTO_IPv6, IPPROTO_UDP, and PROTO_UNKNOWN, respectively. But the same sequence with OPT_IP_EXTHDR on would result in NETPROTO_IPv6, IPPROTO_ROUTING, IPPROTO_FRAGMENT, IPPROTO_UDP, and PROTO_UNKNOWN. (In versions 3.5.0 and 3.5.1, this function behaved as if 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.

fmt_get_payload(Pkt_buffer src, Pkt_buffer dst, STR REF buf);

fmt_get_payload() is like get_payload(), except that it also writes 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 undef; or any of the errors listed in the documentation for get_payload(). A return value of 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 OPT_IP_CKSUM option is set.

get_payload_by_proto(Pkt_buffer src, Pkt_buffer dst, NUM proto);
get_payload_by_layer(Pkt_buffer src, Pkt_buffer dst, NUM 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 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 get_payload().

pkt_truncate(Pkt_buffer pkt, NUM layer, NUM unknown, NUM 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:

Returns the same values as get_payload().

Pcap packet filtering

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.

add_pcap_filter(STR expr);
add_pcap_prefilter(STR expr);
add_pcap_ipfilter(STR expr);

If expr is not undef, add_pcap_filter() sets expr as a global pcap filter expression. If a filter expression was already set (either by this function or by 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 undef, add_pcap_filter() clears any previously set global pcap filter expression.

These functions will not work until set_api(API_PKT) is called. This function returns 0 if successful, or -1 with $! set if there is an error.

add_pcap_prefilter() is similar to 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.

add_pcap_ipfilter() is similar to 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.

get_pcap_filter();
get_pcap_prefilter();
get_pcap_ipfilter();

Returns the text of the global pcap filter expression previously set by add_pcap_filter() or add_pcap_prefilter() and/or by config "filter" or "prefilter" commands. Returns undef if no filter expression has been set.

Cell Reading

General Description

The cell reading functions may be used only with ATM interfaces that have been started. For working with layers 3 and above, the packet reading functions are usually better.

After any of these reading functions are successful, binfop will be a reference to a byte string representing the block info, and cellp will be a reference to a Cell object. binfop can be parsed by the Unpack functions. binfop may be passed a value of undef if the block info will not be needed.

If timeout is undef or omitted, these functions will wait until data are available or an interrupt occurs. But if timeout is not undef, these functions will also return after the amount of time specified in timeout even if there are no data. To set the timeout, input a reference to a 2-element array representing the seconds and microseconds of the timeout, such as [100, 0].

The deny protocol rules are applied by the cell reading functions to filter the cells and determine their protocol. 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.

Return values

(Certain types of errors that were reported as EOF in versions prior 3.5 are now correctly reported as errors.)

Reading Functions

read_cell(SCALAR src, STR REF binfop, Cell cellp, LIST REF timeout = undef);
read_cell_all(STR REF binfop, Cell cellp, LIST REF timeout = undef);

read_cell() reads a single cell from the indicated source; read_cell_all() reads from all open sources. If the OPT_SORT_TIME option is off, read_cell_all() reads cells in the most efficient order (i.e., block order); but if the OPT_SORT_TIME option is on, it will read them in time-sorted order (interleaving cells from blocks of different interfaces). If the OPT_SORT_TIME is set, timeout is ignored (it is always treated as undef).

See the section introduction above for more details and return values.

read_cell_i(SCALAR src, STR REF binfop, Cell cellp, Interval_result int_result,
    LIST REF interval = undef);

read_cell_all_i(STR REF binfop, Cell cellp, Interval_result int_result,
    LIST REF interval = undef);

These functions are like read_cell() and 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 OPT_SORT_TIME option, and whenever *interval seconds have passed or EOF is reached, the functions will return non-undef with cellp == undef 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 undef. When EOF is reached, the final partial interval is returned, and the next call will return undef.

See the section introduction above for more details and return values.

Related Functions

cell_to_pkt(SCALAR iface, Cell cell, Pkt_buffer pkt);

cell is a reference to a Cell object, returned by read_cell. cell_to_pkt fills in the object referenced by pkt with information from cell and iface, for use with functions that expect a Pkt_buffer 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 undef, pkt->protocol will be set to PROTO_UNKNOWN.

The return value is 0 if iface and the cell's vp:vc match a configuration deny rule, otherwise 1.

get_ip(SCALAR iface, REFERENCE data);

This Perl-only function is another shortcut for a common action: taking a Cell or Pkt_buffer and extracting the IPv4-level data from it. iface is the interface from which the Cell or Pkt_buffer was read (by read_cell() or read_pkt()). data is a reference to the Cell or Pkt_buffer itself. Returns the byte string data starting with the IPv4 header, or undef if there was any error. (IP version != 4 counts as an error.) The byte string can then be parsed by the Unpack functions.

Source and Interface Information

These functions provide information about CoralReef sources and interfaces.
next_interface(SCALAR iface);
next_source(SCALAR src);

If iface/src is undef, 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 undef 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:

    $iface = undef;
    while (($iface = next_interface($iface))) {
        # operate on iface 
    }

next_src_iface(SCALAR src, SCALAR iface);
,

Like next_interface(), except it only returns interfaces of src.

source_get_filename(SCALAR src);

Returns the name of the file or network interface of source src, without a coral type prefix. Returns undef if src is bad.

source_get_name(SCALAR src);

Returns the name of the source src, including a coral type prefix, if any. Returns undef if src is bad.

get_source_count();

Returns the number of sources.

interface_get_src(SCALAR iface);

Returns the source descriptor of the source to which interface iface belongs, or undef if iface is bad.

interface_get_type(SCALAR iface);

Return the original (hardware) type of interface iface, or return TYPE_NONE if iface is invalid or its type is unknown.

TYPE_FATM
FORE ATM adaptor device
TYPE_POINT
Apptel POINT device
TYPE_DAG
Waikato DAG device
TYPE_PCAPLIVE
pcap interface

source_get_type(SCALAR src);

Return the type of source src, or 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 interface_get_type(); for file sources, the type will be one of the following:

TYPE_FILE
CoralReef trace file
TYPE_PCAP
pcap (tcpdump) trace file
TYPE_DAGFILE
dagtools trace file
TYPE_TSH
NLANR Time Sequenced Header trace file

interface_get_datalink(SCALAR iface);

Return the data link layer type of interface iface, or PROTO_UNKNOWN if the protocol is unknown, or -1 if iface is bad. The data link layer type is one of the DLT_* (layer 2) constants defined in the Command Usage document.

interface_get_physical(SCALAR iface);

Return the physical layer type of interface iface, or PROTO_UNKNOWN if the protocol is unknown, or -1 if iface is bad. The physical layer type is one of the PHY_* (layer 1) constants defined in the Command Usage document.

interface_get_bandwidth(SCALAR iface);

Return the bandwidth (in kilobits per second) of interface iface, or 0 if the bandwidth is unknown, or -1 if iface is bad.

source_get_number(SCALAR src);
interface_get_number(SCALAR 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 fmt_if_subif().

interface_get_capture_tv(SCALAR iface);

Returns the time (relative to the unix epoch) of the start of the capture on interface iface in the form of (sec, usec), or (undef, undef) if there was an error. It will return (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).

interface_get_capturetime(SCALAR iface);

Returns the integer component of the value that would be returned by interface_get_capture_tv(iface).

cell_size(SCALAR iface);

Returns the size of the cell structure used by iface.

Timestamp Information

These functions get timestamps from packets and interpret them.
get_cell_timestamp(Cell cell);

Defunct. The Cell object now has a member called timestamp.
Old call: $stamp = get_cell_timestamp($cell);
New call: $stamp = $cell->timestamp($iface);

read_clock_sec_nsec(SCALAR iface, SCALAR t);
read_clock_double(SCALAR iface, SCALAR t);

These functions parse the timestamp t, which belongs to a Cell or Pkt_buffer read from interface iface, and convert it to a more useful format.

If the 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 OPT_FATM_RAW_TIME option is set.

read_clock_double() returns the time as floating point number of seconds. Note that some precision may be lost by the conversion to double.

read_clock_sec_nsec() returns the time as a 2-element list of seconds and nanoseconds.

Protocol Information

These functions manipulate protocol information.
proto_abbr(NUM protocol);
proto_desc(NUM protocol);
proto_str(NUM protocol);

Protocol is a prefix_name constant (listed in the Command Usage document) identifying a communication protocol. These functions return a string describing protocol:

dns_op_to_str(NUM qtype);
dns_qtype_to_str(NUM qtype);
dns_qclass_to_str(NUM qclass);

These functions return 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.

dns_str_to_op(STR str);
dns_str_to_qtype(STR str);
dns_str_to_qclass(STR 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).

proto_id(STR 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 proto_{abbr,desc,str}(). Returns PROTO_ILLEGAL if name is not a valid protocol name or abbreviation.

proto_layer(NUM protocol);

Returns the layer number of protocol.

Output File Rotation

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 ROT_AUTO flag, and let libcoral handle everything for you; if you want more control over when rotations occur, you can call the rf_start() and rf_end() functions yourself.

The functions:

rf_open_filehandle(REF handle, STR name, STR tmp = undef, NUM flags = 0);

Creates a Rotfile object to be used for writing a series of files. An iteration of the Rotfile can be started either manually with rf_start(), or automatically at the beginning of each interval if flags has the ROT_AUTO bit set. When an iteration is started, the object referenced by the handle parameter is filled in with a filehandle. 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:

All other % specifiers will be replaced as in strftime(), using the tv parameter of 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 undef, a file with the specified name is opened immediately with each call to rf_start(); otherwise, a temporary file is used, which is renamed to the specified name when 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 rf functions for standard output as well as files, the created rotfile object will behave differently if name is "-":

If flags has the ROT_AUTO bit set, the rotfile will rotate automatically at the beginning of every interval of read_pkt or read_pkts. But if name did not contain any "%" specifiers, only the first (possibly implicit) interval will cause an automatic rf_start call; thus, without "%", the file will not rotate every interval, but you still do not need to call rf_start manually before the first write. Whatever the setting of ROT_AUTO, you can still call rf_end and rf_start to manually rotate the rotfile. But if flags is undefined or does not contain ROT_AUTO, or if you want to write to the rotfile before the first interval, you must call rf_start manually at least once before writing to the file.

If the filename generated from name by 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 is defined and has the ROT_UNSAFE bit set.

This function returns a reference to a newly created Rotfile if successful; failure is indicated by returning undef with $! set and printing a message.

Typical rotating file code has this structure:

    my $handle = new IO::Handle;
    my $rf = rf_open_filehandle($handle, $name);
    rf_start($rf);
    while (there is data) {
	if (it is time to rotate the file) {
	    rf_end($rf);
	    rf_start($rf);
	}
	print $handle data;
    }
    rf_close($rf);

If you wanted to rotate on interval boundaries, you could use the ROT_AUTO flag and omit the calls to rf_start and rf_end.

rf_start(Rotfile rf, LIST REF tv);

Starts an iteration of rotating file rf which has been opened by rf_open_filehandle() . The filename is fixed at this point using the time value in tv for the strftime expansion. tv is a reference to a 2-element array representing the seconds and microseconds time value. If tv is undef, 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 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 $! set and printing a message.

rf_end(Rotfile 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 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 rf_start()). Writing to the file associated with rotfile is not allowed until rf is started again with rf_start(). If the filename was "-", or 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 $! set and printing a message.

rf_close(Rotfile rf);

Implicitly calls 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 rf_close before exiting the program. Returns 0 for success; failure is indicated by returning -1 with $! set and printing a message.

rotate_errfile(LIST REF tv);

Rotates the error file (if the configured error file name contained "%"), using tv as the timestamp for substitutions in the filename as in rf_start(). Returns 0 for success; failure is indicated by returning -1 with $! set and printing a message. If rotation fails, the error file resets to stderr.

CRL Trace Writing

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.

write_open(STR name, STR comment = undef, STR encoding = undef, NUM version = 0);

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. (set_api() must be called with the 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 coral write descriptor (writer) for success, undef for failure. The recommended suffix for CoralReef trace files is ".crl", and for encoded CoralReef trace files is ".enc.crl".

Writes comment and encoding strings into the file header, with encoding version set to version. Comment and encoding default to undef, version defaults to 0. Comment may be up to 255 characters, encoding may be up to 31 characters.

To ensure that all data from all sources are read, you must call stop() on any sources which have not reached EOF. Then, to ensure that all data from all sources are written, you must call write_close() on the writer, before calling close() on the sources.

write_rfopen(STR name, STR tmp = undef, STR comment = undef, STR encoding = undef,
    NUM version = 0);

Like 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 rf_open(). The underlying file is not actually opened until rf_start() or the first write; the timestamp used in filename expansion is the current time. Use write_end() to end the current iteration of a file; a new iteration will be started with the next rf_start() or write. Use write_close() when done writing to the file; it will do an implicit write_end() if one has not been done since the last rf_start() or write. If tmp is not undef, the current iteration file will be given a temporary name, which will be renamed to the permanent name by 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.

write_fopen(FILEHANDLE file, STR comment = undef, STR encoding = undef,
    NUM version = 0);

Like write_open, except it uses the already-open file handle file instead of a filename.

Mixing CoralReef operations with other operations on handle file may have unpredictable effects.

write_init_all(SCALAR writer);
write_init_source(SCALAR writer, SCALAR src);

Prepare to write data from the indicated sources to writer. Returns 0 for success, -1 for failure.

write_init_interface(SCALAR writer, SCALAR iface);

Prepare to write data from a single interface iface to tracefile writer. Returns 0 for success, -1 for failure.

write_cell(SCALAR writer, SCALAR iface, SCALAR cell);

Write cell to writer. iface indicates which interface the cell was read from (as returned by a CoralReef reading function). Returns 0 for success, -1 for failure.

write_close(SCALAR 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 stop() on any sources which have not reached EOF. To ensure that all data from all sources are written, you must call write_close() on the writer, before calling close() on the sources.

Formatted printing

puts(STR 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.

fprint_data(FILEHANDLE file, NUM indent, SCALAR data, NUM len);
print_data(NUM indent, SCALAR data, NUM len);

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. fprint_data is like print_data, except it prints to file instead of stdout.

fprint_cell(FILEHANDLE file, NUM indent, SCALAR iface, SCALAR cell);
print_cell(NUM indent, SCALAR iface, SCALAR cell);

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. fprint_cell is like print_cell, except it prints to file.

fmprint_pkt(FILEHANDLE file, SCALAR iface, SCALAR timestamp, NUM minlayer,
    NUM maxlayer, Pkt_buffer packet, Pkt_buffer header, Pkt_buffer trailer);

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 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.

fprint_pkt(FILEHANDLE file, SCALAR iface, SCALAR timestamp, NUM maxlayer,
    Pkt_buffer packet, Pkt_buffer header, Pkt_buffer trailer);

Equivalent to fmprint_pkt(iface, timestamp, 1, maxlayer, packet, header, trailer).

fmt_if_subif(SCALAR iface, NUM subif);

fmt_if_subif returns a formatted representation of iface id and subif . If the data link type of iface does not have subinterfaces, the format is just the interface number (interface_get_number); if it does, the format is "if[subif]", where subif is formatted as by fmt_subif().

fmt_subif(SCALAR iface, NUM subif);

fmt_subif returns a formatted representation of subif. The format depends on the data link type of iface:

dump(SCALAR src);
dump_all();

Prints information about the indicated sources to the CoralReef errfile, like the application crl_info.

stats(SCALAR src);
stats_all();

Prints statistics about the indicated sources to the CoralReef errfile.

Other

filename(STR str);

Returns a copy of str 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.

in_cksum_add(NUM psum, SCALAR data, NUM len);
in_cksum_result(NUM psum);

Calculates the internet checksum of the string in data. Usage:

  1. initialize psum to 0
  2. call $psum = in_cksum_add($psum, data, len) for each segment of buffer, where data is the segment and len is the length of the segment
  3. call in_cksum_result($psum) to get result.

Segments must be short-aligned. Entire message must have length less than 32768.

Classes

Cell

This class is returned by a call to one of the read_cell functions, representing a cell and its members. All member functions require the interface as an argument, e.g.:

    $header = $cell->header($iface);

This header (or the payload) can then be parsed with the Unpack functions. The Cell member functions are:

    SCALAR timestamp	# time cell was read (interpret with read_clock functions)
    STR header		# link layer header (e.g., ATM)
    STR hec		# HEC that libcoral doesn't include in the header
    STR payload		# link or sub-network layer packet
Pkt_buffer - Buffer structure for packet API
    NUM caplen		# length of data actually captured in buf
    NUM totlen		# total length of pkt (negative if unknown)
    STR buf		# data (in a byte-string format)
    NUM protocol	# protocol (ie, what kind of buffer is this?)

The byte string in buf can be parsed by the Unpack functions.
Pkt_stats - Statistics for packet API
    NUM l2_recv;           # Layer 2 PDUs received
    NUM l2_drop;           # Layer 2 PDUs dropped
    NUM pkts_recv;         # packets received
    NUM pkts_drop;         # packets dropped
    NUM truncated;         # packets truncated by insufficient capture
    NUM driver_corrupt;    # cell looks bad from the capture device
    NUM too_many_vpvc;     # too many simultaneous vpvc pairs
    NUM buffer_overflow;   # AAL5 cell stream > MAX_PACKET_SIZE
    NUM aal5_trailer;      # AAL5 trailer had bad length
    NUM ok_packet;

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.

Most types of interfaces set only a subset of these statistics (the rest will always be zero):

ATM interfaces
l2_recv, l2_drop, pkts_recv, truncated, driver_corrupt, too_many_vpvc, buffer_overflow, aal5_trailer
non-ATM DAG interfaces
pkts_recv, pkts_drop, truncated
live pcap interfaces
pkts_recv, pkts_drop (see also dropinterval)
pcap tracefiles
none
TSH files
pkts_recv, truncated

Pkt_result - Packet results for packet API
    SCALAR timestamp	# time packet was read (interpret with read_clock functions)
    Pkt_buffer packet	# link or sub-network layer packet
    Pkt_buffer header	# link layer header (eg, ATM)
    Pkt_buffer trailer	# link layer trailer (eg, AAL5)
    NUM subiface	# sub-interface id (ATM VPVC or VLAN ID)

The subiface field can be formatted with fmt_subif().

Interval_result - Interval results for packet API
    LIST begin		# beginning of interval (sec, usec)
    LIST end		# end of interval (sec, usec)
    Pkt_stats stats	# statistics for interval
Rotfile - Rotating file handle

An opaque structure that should be accessed through the rf_* functions.