Getting Started with Snooper: Watching Informix Traffic Without Touching the App
Snooper (oni_snoop) sits between an Informix client —
ESQL/C, a 4GL program, dbaccess, anything speaking the SQLI
wire protocol — and the real IDS server. It decodes every PFPDU in
both directions and writes a TSV event line to standard error, while the
forward path stays a raw TCP byte replay, so the snoop adds no latency to
the traffic it's observing. Nothing about the application, its connect
strings, or its SQL changes; the only thing that moves is which port the
client connects to.
Drop the binary in place
oni_snoop is a single stripped ELF binary — no package,
no config file, no Informix CSDK on the host. It talks SQLI on the wire
directly, so there's no libifsql.so, no setcsdk,
no INFORMIXDIR to set up:
$ sudo install -m 0755 oni_snoop /usr/local/bin/
$ oni_snoop --help
From v4.0 the binary uses a hybrid link so TLS can call the system
OpenSSL — libgcc helpers are static, libssl /
libcrypto / libz / libc resolve
from the host (present by default on any modern distro). The plaintext
path needs none of that; TLS is opt-in per flag. RPM and DEB packages are
also available if you'd rather resolve the OpenSSL dependency through a
package manager than a hand-copied binary — see
Install.
Insert it at the client's sqlhosts
The snoop and IDS can't share a port, so the snoop binds a different one
and the client's sqlhosts is repointed at it. The IDS server
itself is untouched — same port, same bind address, same
onconfig. With IDS on 192.168.203.4:9088, run
the snoop on 9089 and change the client's entry from 9088 to
9089:
# client $INFORMIXSQLHOSTS — repoint the one entry
myids onsoctcp 192.168.203.4 9089 # was 9088; 9089 is the snoop
# on the IDS host (IDS still listening on 9088):
$ oni_snoop --listen 0.0.0.0:9089 --upstream 127.0.0.1:9088
The snoop can just as easily run on a separate host between the app tier
and the database tier — the sqlhosts entry then names that host,
and --upstream names the real IDS. Either way, the whole
change lives on the client side; nothing about the running IDS instance
moves, and there's no server restart involved.
Capture a few seconds of traffic
Run the snoop in the background, reproduce the workload of interest, then stop it cleanly:
$ oni_snoop --listen 0.0.0.0:9089 --upstream 198.51.100.42:19089 \
2>snoop.log &
SPID=$!
# ...reproduce the workload of interest...
$ kill -INT $SPID; wait $SPID
Every line is TSV: wall_ts, mono_us,
conn, dir (> request /
< response), token, len,
round_us, stmt_us, gap_us, then a
type-specific summary — the decoded SQL text on a
ONI_PREPARE/ONI_COMMAND row, the decoded column
values on a ONI_TUPLE row, the SQLCODE and server message on
an ONI_ERR row. Lines starting with # are
banner/header commentary, never data, so a parser can strip them and
split everything else on \t. Full column reference:
Output Schema.
Find the slowest round trips
The closing ONI_EOT of a server response carries the full
round-trip latency in round_us (column 7). One
awk pass surfaces the slow ones, then a second pulls the SQL
text for whichever connection stands out:
$ awk -F'\t' '$5=="ONI_EOT" && $4=="<" && $7+0 > 100000 {
printf "%8d us conn=%s\n", $7, $3
}' snoop.log
142057 us conn=4
1830204 us conn=5
$ awk -F'\t' '$3=="5" && ($5=="ONI_PREPARE" || $5=="ONI_COMMAND")' snoop.log
2026-04-29T01:06:39.210066Z 3529872 5 > ONI_COMMAND 48 - 0 484 sql="CREATE DATABASE oninit WITH BUFFERED LOG"
Conn 5's slow round trip was a CREATE DATABASE —
expected, not a regression. The same pattern works for any latency
outlier: find the slow ONI_EOT, then grep that connection's
ONI_PREPARE/ONI_COMMAND row for the statement
that caused it.
Keep a steady-state capture lean
For longer-running observation, ONI_TUPLE/ONI_EOT
chatter dominates the log. --only limits capture to
statement boundaries and errors so the file stays compact without losing
per-connection timing — round_us, stmt_us,
and gap_us still reflect the full conversation, not just the
filtered rows:
$ oni_snoop --listen 0.0.0.0:9089 --upstream 198.51.100.42:19089 \
--out /var/log/oni_snoop.log \
--only=ONI_PREPARE,ONI_COMMAND,ONI_DONE,ONI_ERR,ONI_PUTERR
TLS in the middle, when it's needed
From v4.0 the snoop can terminate TLS on the listen side, re-encrypt to the real IDS, or both — decoding the same plaintext PFPDU stream in between either way. A typical end-to-end setup, terminating a modern client and re-encrypting upstream:
$ oni_snoop --listen 0.0.0.0:9089 --upstream 198.51.100.42:9088 \
--tls-listen --tls-listen-cert snoop.pem --tls-listen-key snoop.key \
--tls-upstream --tls-upstream-ca ids-ca.pem \
2>/var/log/oni_snoop.log
--conssl-cfg can reuse an existing Informix
conssl.cfg keystore instead of separate PEM files —
see Operations for the flag reference and
the keystore export step.
Where to go next
The full worked examples cover finding a server pause mid-response, reconstructing one statement's entire lifecycle, and building a per-statement latency report from a capture. Output Schema documents every column and every per-token summary format, and the Snooper product page covers install paths, deployment placement, and download.