Farsight's Advanced Exchange Access: The C Programming API, Part One
By Mike Schiffman
This article is first in a multi-part blog series intended to introduce and
acquaint the reader with Farsight Security's AXA C API. This article
libaxa C programming API and showcases a simple working
This article assumes the reader is familiar with AXA and related technologies. To brush up, the following Farsight Security Blog articles are recommended reading:
- Farsight's Advanced Exchange Access, Volume 1: Introduction to AXA
- Farsight's Advanced Exchange Access, Volume 2: Introduction to Sratool
- Farsight's Advanced Exchange Access,, Volume 3: Introduction to Sratunnel
This article, geared towards intermediate-level C programmers, is by no means
an exhaustive API reference. For that, the reader is directed to the
accompanying Doxygen-based API manual.
This article covers
sratesttool is a Unix command-line utility capable of the following:
- Connecting to an SRA server
- Enabling an SIE channel
- Setting an AXA watch
- Streaming watch hits to the console
Throughout this short series, we'll examine how all of this done. In this first article, we'll cover the main driver which contains the initialization code and controls the main program flow.
$ sratesttool -s tls:user@sraserver,1021 -c 255 -w ch=255 Farsight Security SRA Test Tool connecting to tls:user@sraserver,1021... connected parsing watch: ch=255... parse ch=255 OK setting watch on server... watch set OK parsing channel: 255... parse 255 OK enabling channel on server... channel enabled OK NMSG watch hit, channel: 255 @ 2015-07-29T19:13:21.111788988 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:21.612488985 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:22.113173007 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:22.613782882 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:23.114434957 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:23.615050077 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:24.115665912 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:24.616344928 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:25.117007970 NMSG watch hit, channel: 255 @ 2015-07-29T19:13:25.617640972 ^C10 total watch hits
sratesttool is not a full implementation of the AXA protocol. It
is meant as a tutorial on how to stand up a simple connection to the SRA
server, issue a few commands, and stream data.
Sratesttool is only written
to work for TLS and many
libaxa code paths are not taken nor is robust error
checking performed. It is intended as an entry-level program to get the
reader familiar with the AXA protocol and the
The code for
sratesttool is contained in a single source file that can be
compiled into a fully functional program. To build it, you'll need to link
libaxa library. You can find the source code
here and if you're a Debian-user, the
Debian package here.
While we will cover the source code across several articles, the full source code is available for download from Farsight Security's blog-code GitHub page.
The code walk-through begins below.
The first section contains the source code license and the standard C header file include progression:
The following server-specific functions wrap
libaxa functions. We'll explore
all of them in detail later, for now it is sufficient to understand what they
srvr_connect(): Connects to the server.
srvr_cmd(): Send a command to the server and wait for a response.
srvr_wait_resp(): Wait for a response from the server.
srvr_process(): Process a message from the server.
srvr_disconnect(): Disconnects from the server.
Miscellaneous functions are declared next:
There is a small collection of global data:
static axa_client_t client: Opaque blob, contains all client state.
static const char *server_str: The transport/username/server string.
static const char *watch_str: The watch string.
static const char *channel_str: The channel string.
static int terminated: When this value is > 0, it's time to quit
static uint64_t hits: Number of watch hits
Main Function Argument Processing
The initial stanza of main function is standard and uninteresting command-line argument processing:
Next, we encounter the first
libaxa API function calls. The first stanza
sets up the AXA logging substructure. One of the conveniences
is an opaque "three stream" logging / syslog interface. With
have the following logging streams:
- trace: Tracing stream for server-side error messages
- error: Error stream for client-side error messages
- accounting: Accounting information (packet sent/loss/transit/limit totals)
Sratesttool does not use the syslog interface and as such initializes the
loggers to emit messages only to
stderr. For more information, see the
Doxygen manual for
After the logging initialization, we initialize the AXA client context. This is an opaque structure that contains all of the state required to open and maintain an SRA server connection.
Next comes the signal processing. In order to provide an orderly exit from
signals that cause the termination of the
sratesttool process with
garbage collection and a statistics report, we catch and hand them off to our
simple signal handler.
At this point, our AXA client is initialized and
sratesttool is ready for
business. It then reaches out and tries to make a connection to the server. If
something goes wrong,
sratesttol will bail. More robust implementations such
axaclientd will attempt to
reconnect using an exponential back off and retry algorithm.
A lot of core
libaxa code is contained in the
- Opening the client connection to the server.
- Parsing the watch string and setting the watch on the server.
- Parsing the channel string and enabling the channel on the server.
- Starting the data stream.
In the next article we will explore all of these in detail.
We now descend into the infinite event loop. The first check will always be to
sratesttool needs to exit (as the result of an asynchronous event such
as the user hitting ctrl-c at the console).
The call to
libaxa to simply wait up to 10ms for input
from the server. Internally,
libaxa polls its list of file descriptors to
look for input from the server. If the timer expires and no data is available,
axa_io_wait() will return
AXA_IO_BUSY which just returns control to the top
of the loop. If data is waiting to be read,
AXA_IO_OK will be returned and
srvr_process() will be called to handle it (covered in detail later). For
sratesttool, most of the time, this should be watch hits. If something goes
wrong when polling,
AXA_IO_ERR is returned and
sratesttool will disconnect
Also of note,
axa_io_wait() is called without keepalive functionality (not
needed for this example) and without tunnel debugging (only used for SSH-based
The next article in the AXA C API series will continue the discussion of
sratesttool and cover some of the core
Mike Schiffman is a Packet Esotericist for Farsight Security, Inc.