<abstract>
This is the documentation for <tt>ulogd-2.x</tt>, the second generation
Netfilter Userspace logging daemon. ulogd makes use of the Linux >= 2.6.14
-nfnetlink_log and nfnetlink_conntrack subsystems, but also provides backwards compatibility for Linux
->= 2.4.0 ipt_ULOG.
+nfnetlink_log and nfnetlink_conntrack subsystems.
</abstract>
<toc>
<sect1>Linux kernel
<p>
To use the NFCT or NFLOG input plugin, you will need a 2.6.14 or later kernel.
-For old-style ULOG logging, you need a kernel >= 2.4.18.
<sect1>Userspace libraries
<p>
this option to later tell from which rule the packet was logged.
</descrip>
-<sect1>iptables ULOG target
-<sect2>Quick Setup
-<p>
-Just add rules using the ULOG target to your firewalling chain. A very basic
-example:
-<tscreen><verb>
-iptables -A FORWARD -j ULOG --ulog-nlgroup 32 --ulog-prefix foo
-</verb></tscreen>
-<p>
-To increase logging performance, try to use the
-<tscreen><verb>
---ulog-qthreshold N
-</verb></tscreen>
-option (where 1 < N <= 50). The number you specify is the amount of packets
-batched together in one multipart netlink message. If you set this to 20, the
-kernel schedules ulogd only once every 20 packets. All 20 packets are then
-processed by ulogd. This reduces the number of context switches between kernel
-and userspace.
-<p>
-Of course you can combine the ULOG target with the different netfilter match
-modules. For a more detailed description, have a look at the netfilter
-HOWTO's, available on the netfilter homepage.
-<sect2>ULOG target reference
-<p>
-<descrip>
-<tag>--ulog-nlgroup N</tag>
-The number of the netlink multicast group to which ULOG'ed packets are sent.
-You will have to use the same group number in the ULOG target and ulogd in
-order to make logging work.
-<tag>--ulog-cprange N</tag>
-Copyrange. This works like the 'snaplen' parameter of tcpdump. You can specify
-a number of bytes up to which the packet is copied. If you say '40', you will
-receive the first fourty bytes of every packet. Leave it to <tt>0</tt>
-<tag>--ulog-qthreshold N</tag>
-Queue threshold. If a packet is matched by the iptables rule, and already N
-packets are in the queue, the queue is flushed to userspace. You can use this
-to implement a policy like: Use a big queue in order to gain high performance,
-but still have certain packets logged immediately to userspace.
-<tag>--ulog-prefix STRING</tag>
-A string that is associated with every packet logged by this rule. You can use
-this option to later tell from which rule the packet was logged.
-</descrip>
-
-<sect2>ipt_ULOG module parameters
-<p>
-The ipt_ULOG kernel module has a couple of module loadtime parameters which can
-(and should) be tuned to accomodate the needs of the application:
-<descrip>
-<tag>nlbufsiz N</tag>
-Netlink buffer size. A buffer of the specified size N is allocated for every
-netlink group that is used. Please note that due to restrictions of the kernel
-memory allocator, we cannot have a buffer size > 128kBytes. Larger buffer
-sizes increase the performance, since less kernel/userspace context switches
-are needed for the same amount of packets. The backside of this performance
-gain is a potentially larger delay. The default value is 4096 bytes, which is
-quite small.
-<tag>flushtimeout N</tag>
-The flushtimeout determines, after how many clock ticks (on alpha: 1ms, on
-x86 and most other platforms: 10ms time units) the buffer/queue is to be
-flushed, even if it is not full. This can be used to have the advantage of a
-large buffer, but still a finite maximum delay introduced. The default value
-is set to 10 seconds.
-</descrip>
-Example:
-<tscreen><verb>
-modprobe ipt_ULOG nlbufsiz=65535 flushtimeout=100
-</verb></tscreen>
-This would use a buffer size of 64k and a flushtimeout of 100 clockticks (1 second on x86).
-
<sect1>ulogd
<p>
ulogd is what this is all about, so let's describe it's configuration...
-<sect2>ulogd_inppkt_ULOG.so
-<p>
-The good old ipt_ULOG input plugin. This basically emulates ulogd-1.x which
-didn't have input plugins.
-<descrip>
-<tag>nlgroup</tag>
-The number of the netlink multicast group to which ULOG'ed packets are sent.
-You will have to use the same group number in the ULOG target and nin the input plugin.
-<tag>numeric_label</tag>
-You can use this label to store information relative to the logging. The administrator can define a convention which can be used later to differenciate packet. For example, it can store the severity of the logged event.
-</descrip>
-
-
-
<sect1>Interpreter plugins
<p>
+++ /dev/null
-/* ulogd_inppkt_ULOG.c - stackable input plugin for ULOG packets -> ulogd2
- *
- * (C) 2004-2005 by Harald Welte <laforge@gnumonks.org>
- */
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-
-#include <ulogd/ulogd.h>
-#include <libipulog/libipulog.h>
-
-#ifndef ULOGD_NLGROUP_DEFAULT
-#define ULOGD_NLGROUP_DEFAULT 32
-#endif
-
-/* Size of the socket receive memory. Should be at least the same size as the
- * 'nlbufsiz' module loadtime parameter of ipt_ULOG.o
- * If you have _big_ in-kernel queues, you may have to increase this number. (
- * --qthreshold 100 * 1500 bytes/packet = 150kB */
-#define ULOGD_RMEM_DEFAULT 131071
-
-/* Size of the receive buffer for the netlink socket. Should be at least of
- * RMEM_DEFAULT size. */
-#define ULOGD_BUFSIZE_DEFAULT 150000
-
-struct ulog_input {
- struct ipulog_handle *libulog_h;
- unsigned char *libulog_buf;
- struct ulogd_fd ulog_fd;
-};
-
-/* configuration entries */
-
-static struct config_keyset libulog_kset = {
- .num_ces = 4,
- .ces = {
- {
- .key = "bufsize",
- .type = CONFIG_TYPE_INT,
- .options = CONFIG_OPT_NONE,
- .u.value = ULOGD_BUFSIZE_DEFAULT,
- },
- {
- .key = "nlgroup",
- .type = CONFIG_TYPE_INT,
- .options = CONFIG_OPT_NONE,
- .u.value = ULOGD_NLGROUP_DEFAULT,
- },
- {
- .key = "rmem",
- .type = CONFIG_TYPE_INT,
- .options = CONFIG_OPT_NONE,
- .u.value = ULOGD_RMEM_DEFAULT,
- },
- {
- .key = "numeric_label",
- .type = CONFIG_TYPE_INT,
- .options = CONFIG_OPT_NONE,
- .u.value = 0,
- },
-
- }
-};
-enum ulog_keys {
- ULOG_KEY_RAW_MAC = 0,
- ULOG_KEY_RAW_PCKT,
- ULOG_KEY_RAW_PCKTLEN,
- ULOG_KEY_RAW_PCKTCOUNT,
- ULOG_KEY_OOB_PREFIX,
- ULOG_KEY_OOB_TIME_SEC,
- ULOG_KEY_OOB_TIME_USEC,
- ULOG_KEY_OOB_MARK,
- ULOG_KEY_OOB_IN,
- ULOG_KEY_OOB_OUT,
- ULOG_KEY_OOB_HOOK,
- ULOG_KEY_RAW_MAC_LEN,
- ULOG_KEY_OOB_FAMILY,
- ULOG_KEY_OOB_PROTOCOL,
- ULOG_KEY_RAW_LABEL,
-};
-
-static struct ulogd_key output_keys[] = {
- [ULOG_KEY_RAW_MAC] = {
- .type = ULOGD_RET_RAW,
- .flags = ULOGD_RETF_NONE,
- .name = "raw.mac",
- .ipfix = {
- .vendor = IPFIX_VENDOR_IETF,
- .field_id = IPFIX_sourceMacAddress,
- },
- },
- [ULOG_KEY_RAW_PCKT] = {
- .type = ULOGD_RET_RAW,
- .flags = ULOGD_RETF_NONE,
- .name = "raw.pkt",
- .ipfix = {
- .vendor = IPFIX_VENDOR_NETFILTER,
- .field_id = 1,
- },
- },
- [ULOG_KEY_RAW_PCKTLEN] = {
- .type = ULOGD_RET_UINT32,
- .flags = ULOGD_RETF_NONE,
- .name = "raw.pktlen",
- .ipfix = {
- .vendor = IPFIX_VENDOR_IETF,
- .field_id = 1
- },
- },
- [ULOG_KEY_RAW_PCKTCOUNT] = {
- .type = ULOGD_RET_UINT32,
- .flags = ULOGD_RETF_NONE,
- .name = "raw.pktcount",
- .ipfix = {
- .vendor = IPFIX_VENDOR_IETF,
- .field_id = 2
- },
- },
- [ULOG_KEY_OOB_PREFIX] = {
- .type = ULOGD_RET_STRING,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.prefix",
- },
- [ULOG_KEY_OOB_TIME_SEC] = {
- .type = ULOGD_RET_UINT32,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.time.sec",
- .ipfix = {
- .vendor = IPFIX_VENDOR_IETF,
- .field_id = 22
- },
- },
- [ULOG_KEY_OOB_TIME_USEC] = {
- .type = ULOGD_RET_UINT32,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.time.usec",
- },
- [ULOG_KEY_OOB_MARK] = {
- .type = ULOGD_RET_UINT32,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.mark",
- },
- [ULOG_KEY_OOB_IN] = {
- .type = ULOGD_RET_STRING,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.in",
- },
- [ULOG_KEY_OOB_OUT] = {
- .type = ULOGD_RET_STRING,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.out",
- },
- [ULOG_KEY_OOB_HOOK] = {
- .type = ULOGD_RET_UINT8,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.hook",
- .ipfix = {
- .vendor = IPFIX_VENDOR_NETFILTER,
- .field_id = IPFIX_NF_hook,
- },
- },
- [ULOG_KEY_RAW_MAC_LEN] = {
- .type = ULOGD_RET_UINT16,
- .flags = ULOGD_RETF_NONE,
- .name = "raw.mac_len",
- },
- [ULOG_KEY_OOB_FAMILY] = {
- .type = ULOGD_RET_UINT8,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.family",
- },
- [ULOG_KEY_OOB_PROTOCOL] = {
- .type = ULOGD_RET_UINT16,
- .flags = ULOGD_RETF_NONE,
- .name = "oob.protocol",
- },
- [ULOG_KEY_RAW_LABEL] = {
- .type = ULOGD_RET_UINT8,
- .flags = ULOGD_RETF_NONE,
- .name = "raw.label",
- },
-
-};
-
-static int interp_packet(struct ulogd_pluginstance *ip, ulog_packet_msg_t *pkt)
-{
- struct ulogd_key *ret = ip->output.keys;
-
- if (pkt->mac_len) {
- okey_set_ptr(&ret[ULOG_KEY_RAW_MAC], pkt->mac);
- okey_set_u16(&ret[ULOG_KEY_RAW_MAC_LEN], pkt->mac_len);
- }
-
- okey_set_u8(&ret[ULOG_KEY_RAW_LABEL], ip->config_kset->ces[3].u.value);
-
- /* include pointer to raw ipv4 packet */
- okey_set_ptr(&ret[ULOG_KEY_RAW_PCKT], pkt->payload);
- okey_set_u32(&ret[ULOG_KEY_RAW_PCKTLEN], pkt->data_len);
- okey_set_u32(&ret[ULOG_KEY_RAW_PCKTCOUNT], 1);
-
- okey_set_ptr(&ret[ULOG_KEY_OOB_PREFIX], pkt->prefix);
-
- /* god knows why timestamp_usec contains crap if timestamp_sec == 0
- * if (pkt->timestamp_sec || pkt->timestamp_usec) { */
- if (pkt->timestamp_sec) {
- okey_set_u32(&ret[ULOG_KEY_OOB_TIME_SEC], pkt->timestamp_sec);
- okey_set_u32(&ret[ULOG_KEY_OOB_TIME_USEC], pkt->timestamp_usec);
- } else {
- ret[ULOG_KEY_OOB_TIME_SEC].flags &= ~ULOGD_RETF_VALID;
- ret[ULOG_KEY_OOB_TIME_USEC].flags &= ~ULOGD_RETF_VALID;
- }
-
- okey_set_u32(&ret[ULOG_KEY_OOB_MARK], pkt->mark);
- okey_set_ptr(&ret[ULOG_KEY_OOB_IN], pkt->indev_name);
- okey_set_ptr(&ret[ULOG_KEY_OOB_OUT], pkt->outdev_name);
-
- okey_set_u8(&ret[ULOG_KEY_OOB_HOOK], pkt->hook);
-
- /* ULOG is IPv4 only */
- okey_set_u8(&ret[ULOG_KEY_OOB_FAMILY], AF_INET);
- /* Undef in ULOG but necessary */
- okey_set_u16(&ret[ULOG_KEY_OOB_PROTOCOL], 0);
-
- ulogd_propagate_results(ip);
- return 0;
-}
-
-static int ulog_read_cb(int fd, unsigned int what, void *param)
-{
- struct ulogd_pluginstance *upi = (struct ulogd_pluginstance *)param;
- struct ulogd_pluginstance *npi = NULL;
- struct ulog_input *u = (struct ulog_input *) &upi->private;
- ulog_packet_msg_t *upkt;
- int len;
-
- if (!(what & ULOGD_FD_READ))
- return 0;
-
- while ((len = ipulog_read(u->libulog_h, u->libulog_buf,
- upi->config_kset->ces[0].u.value))) {
- if (len <= 0) {
- if (errno == EAGAIN)
- break;
- /* this is not supposed to happen */
- ulogd_log(ULOGD_ERROR, "ipulog_read = %d! "
- "ipulog_errno = %d (%s), "
- "errno = %d (%s)\n",
- len, ipulog_errno,
- ipulog_strerror(ipulog_errno),
- errno, strerror(errno));
- break;
- }
- while ((upkt = ipulog_get_packet(u->libulog_h,
- u->libulog_buf, len))) {
- /* since we support the re-use of one instance in
- * several different stacks, we duplicate the message
- * to let them know */
- llist_for_each_entry(npi, &upi->plist, plist)
- interp_packet(npi, upkt);
- interp_packet(upi, upkt);
- }
- }
- return 0;
-}
-
-static int init(struct ulogd_pluginstance *upi)
-{
- struct ulog_input *ui = (struct ulog_input *) &upi->private;
-
- ui->libulog_buf = malloc(upi->config_kset->ces[0].u.value);
- if (!ui->libulog_buf) {
- ulogd_log(ULOGD_ERROR, "Out of memory\n");
- goto out_buf;
- }
-
- ui->libulog_h = ipulog_create_handle(
- ipulog_group2gmask(upi->config_kset->ces[1].u.value),
- upi->config_kset->ces[2].u.value);
- if (!ui->libulog_h) {
- ulogd_log(ULOGD_ERROR, "Can't create ULOG handle\n");
- goto out_handle;
- }
-
- ui->ulog_fd.fd = ipulog_get_fd(ui->libulog_h);
- ui->ulog_fd.cb = &ulog_read_cb;
- ui->ulog_fd.data = upi;
- ui->ulog_fd.when = ULOGD_FD_READ;
-
- ulogd_register_fd(&ui->ulog_fd);
-
- return 0;
-
-out_handle:
- free(ui->libulog_buf);
-out_buf:
- return -1;
-}
-
-static int fini(struct ulogd_pluginstance *pi)
-{
- struct ulog_input *ui = (struct ulog_input *)pi->private;
-
- ulogd_unregister_fd(&ui->ulog_fd);
-
- return 0;
-}
-
-struct ulogd_plugin libulog_plugin = {
- .name = "ULOG",
- .input = {
- .type = ULOGD_DTYPE_SOURCE,
- .keys = NULL,
- .num_keys = 0,
- },
- .output = {
- .type = ULOGD_DTYPE_RAW,
- .keys = output_keys,
- .num_keys = ARRAY_SIZE(output_keys),
- },
- .start = &init,
- .stop = &fini,
- .config_kset = &libulog_kset,
- .version = VERSION,
-};
-
-void __attribute__ ((constructor)) initializer(void)
-{
- ulogd_register_plugin(&libulog_plugin);
-}