Debugging¶
Unittests¶
To run unittests from the build directory:
./src/suricata -u -l /tmp/
The -l option is added to overwrite the default log dir. Some tests write logs. This way we don't need root/sudo rights to complete the tests.
valgrind¶
Running unittests with valgrind enabled:
valgrind -v --trace-children=yes ./src/suricata -u -l /tmp/
The trace children option is necessary if running from the build directory, as "src/suricata" is a script in that case. This is caused by us bundling the libhtp.
gdb with core files¶
If Suricata crashed with a core dump, lots of info can be retrieved from this core file.
gdb /path/to/suricata /path/to/core
Getting info about the traffic¶
For example, in a bt like this:
(gdb) bt #0 0x00007f0302c1af47 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x00007f0302c1917e in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x00000000005ac84d in StreamTcpReassembleAppLayer (tv=0x23258570, ra_ctx=0x7f02b8001540, ssn=0x7f027c72c9e0, stream=0x7f027c72ca30, p=0x25057a0) at stream-tcp-reassemble.c:2979 #3 0x0000000000000000 in ?? ()
You can get to the traffic into by going to a frame where you have the
"p" (Packet) variable. In this case frame 2:
(gdb) frame 2
There you can print the entire packet:
(gdb) print *p
Or just individual fields:
(gdp) print p->proto (gdp) print p->sp (gdp) print p->dp
Addresses are bit more involved:
(gdb) print p->src.address.address_un_data32[0] (gdb) print p->dst.address.address_un_data32[0]
This gives you an unsigned int value, you'll have to convert that to the
dotted quad notation yourself.
Example:
(gdb) print p->src.address.address_un_data32[0] $2 = 721529024
Perl is helpful here:
$ perl -MSocket -e "print inet_ntoa(pack('V',721529024)) . \"\n\";" 192.168.1.43
For IPv6 you'll have to use:
(gdb) print p->src.address.address_un_data32[0] (gdb) print p->src.address.address_un_data32[1] (gdb) print p->src.address.address_un_data32[2] (gdb) print p->src.address.address_un_data32[3]
To figure out whether it's 4 or 6, print:
(gdb) print p->src.family
Here 2 is IPv4, 10 is IPv6.
In general, the same is true for 'frames' where only the Flow can be accessed. This usually has 'f' or 'flow' as variable name.
(gdb) print *f
Like with the packet, the flow has proto, sp, dp, and src and dst fields.
The flow can be accessed from the packet as well, through p->flow.