Farsight's Advanced Exchange Access: The C Programming API, Part Two
By Mike Schiffman
This article is the second in a multi-part blog series intended to introduce and
acquaint the reader with Farsight Security's AXA C API. This article continues
the introduction of the
libaxa C programming API.
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
Additionally, if you haven't yet, you'll want to read the first article in the series:
We pick up right where we left in the first article.
Connecting To The Server And Setting State
srvr_* function we'll dissect is a big one, responsible for
connecting to the SRA server, setting the watch and enabling the channel.
First, we explain important AXA-specific data types / variables:
axa_p_watch_t watch: An AXA watch object; contains all of the state for an AXA watch specification.
axa_p_channel_t channel: An AXA channel object; contains all of the state for an AXA channel specification.
axa_emsg_t emsg: An AXA error message object; if an error occurs in a
libaxafunction, this will contain details on what caused it.
axa_tag_t cur_tag: A tag is an identifier used to uniquely "tag" specific events during the lifetime of an AXA session. To refer to these events, the client or server will use the tag. Some AXA messages do not require tags, in which case we will use the value
AXA_TAG_NONE. Required tags must be unique during the lifetime of the corresponding client request. Some client requests such as a watch can last indefinitely and will elicit many server responses all with the same tag.
Connect To The Server
axa_client_open() function attempts to open a server connection and
establish state for our client's connection. The first two arguments, passed
by reference, will be filled in by
emsg if something goes wrong,
client if something doesn't). The next argument,
server_str is a specially
crafted text string of the following format:
- transport: SRA supports either TLS or SSH as an encrypted transport.
Sratesttoolonly supports TLS, so the argument here should be
- user: The username of the user. This is provisioned by Farsight Security when your account is turned up.
- server: The SRA server IP address or hostname.
- port: Used only for TLS, to specify the port the SRA server listens for TLS connections.
The next boolean argument specifies whether or not to expect to connect to a RAD server or an SRA server. Since this is an SRA tool, "RAD" (Real-time Anomaly Detection) mode is not enabled. Likewise, since we are using TLS, SSH tunnel debugging is not enabled.
The input socket buffer size is set to be
256 * 1024, a larger than normal
value due to the potentially high-volume of SIE data transited by SRA.
Internally, this will be requested to be set by
The return value from
axa_client_open() is evaluated in a small switch table
which checks for errors or non sequitur as per the following:
AXA_CONNECT_ERR: Something went terribly wrong, print
AXA_CONNECT_TEMP: A temporary error occurred, print
emsgand quit. In more robust implementations, we would probably back off and try again.
AXA_CONNECT_DONE: The connection is complete.
AXA_CONNECT_NOP: The connection is complete and an
AXA_P_OP_NOPis sent to the server. This is done so the client can tell the server the version of the AXA protocol that the client is using. If need be, the server can down shifting to an old version of the protocol.
AXA_CONNECT_USER: For TCP-based socket connections, does not apply to TLS (or SSH) connections and should be an error in this case.
Pause The Output
After successfully connecting to the server but before any watches are set or
channels are enabled, an
AXA_P_OP_PAUSE command is sent. This "pause"
command tells the server to stop sending data and to actually discard it,
server side. This is a global switch the pauses data output for all channels
for the current user.
This is the first time we encounter the
srvr_cmd() function which is used to
send commands and data to the SRA server. We'll cover it in detail later but
for now it's important to note that it accepts an AXA tag argument:
AXA_TAG_MIN: The "minimum" tag value, this is a non-specific tag value used when we need a tag but don't care about which one.
And two AXA opcode arguments:
AXA_P_OP_PAUSE: The opcode representing the action requested of the server. In this case to pause the data flow.
AXA_P_OP_OK: The opcode expected from the server the for the operation to be considered a success.
Parse and Set the Watch
Next, the watch string is parsed with a call to
axa_parse_watch(). If there
is a problem parsing it,
libaxa will do its best to emit a helpful error
emsg. However, if the watch string makes no sense, the function
will fail with an empty
For a verbose treatment of what SRA watches can look like, see sratool(1).
After successfully parsing the watch, it is set on the server with a call to
srvr_cmd() with an AXA opcode of
AXA_P_OP_WATCH and an expected server
Parse and Enable the Channel
Next, in the same manner as above, the channel string is parsed and enabled on the server.
Un-pause The Output
After the channel is enabled,
sratesttool is ready to start streaming watch
hits. It lets the server know by sending the opcode
AXA_P_OP_GO which tells
the server its time to un-pause the output.
Now the server connection process is complete and the function returns successfully.
Run a Command on The Server
The next function, as we've already seen,
srvr_cmd(), is used to send
opcodes and data to the SRA server. It is a wrapper to
with additional code to disconnect via
srvr_disconnect() if a problem
We've already covered the tag and opcode arguments, but the
function also accepts data in the form of an opaque pointer and its length.
The call to
axa_client_send() fires off the request to the server and, if
it doesn't fail, a call to
srvr_wait_resp() is made to process the response.
For that, and the rest of the code, you'll have to wait until the third and final installment of this series.
The third and final article in the AXA C API series will conclude the
Mike Schiffman is a Packet Esotericist for Farsight Security, Inc.