A pfctl_handle embeds an snl_state whose arena backs both netlink
requests and reply parsing. The arena only grows; it is reset only
by snl_free() in pfctl_close().
Consumers that keep one handle open and poll pf repeatedly -
for example the bsnmpd snmp_pf module - therefore never reset it.
Using DTrace I was able to trace a memory leak:
=== Memory leak, data leaked = 220201152, count = 3 libc.so.7`calloc+0x16e snmp_pf.so.6`pfctl_get_rule_h+0xe snmp_pf.so.6`0xea40b321cf3 snmp_pf.so.6`0xea40b3219fb snmp_pf.so.6`0xea40b321ad9 snmp_pf.so.6`0xea40b3212d9 snmp_pf.so.6`pf_lbltable+0x36 libbsnmp.so.7`snmp_getbulk+0x37f bsnmpd`snmp_input_finish+0x213 bsnmpd`snmpd_input+0x30e libbegemot.so.4`poll_dispatch+0x4af bsnmpd`main+0x9da libc.so.7`__libc_start1+0x12f bsnmpd`_start+0x21
After this commit we reset the arena at the start of each transaction,
in a new pfctl_begin_nl() helper.