Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0af5f6c1 authored by Harald Welte's avatar Harald Welte Committed by David S. Miller
Browse files

[NETFILTER] nfnetlink_log: add sequence numbers for log events



By using a sequence number for every logged netfilter event, we can
determine from userspace whether logging information was lots somewhere
downstream.

The user has a choice of either having per-instance local sequence
counters, or using a global sequence counter, or both.

Signed-off-by: default avatarHarald Welte <laforge@netfilter.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5ee95612
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ enum nfulnl_attr_type {
	NFULA_PAYLOAD,			/* opaque data payload */
	NFULA_PREFIX,			/* string prefix */
	NFULA_UID,			/* user id of socket */
	NFULA_SEQ,			/* instance-local sequence number */
	NFULA_SEQ_GLOBAL,		/* global sequence number */

	__NFULA_MAX
};
@@ -77,6 +79,7 @@ enum nfulnl_attr_config {
	NFULA_CFG_NLBUFSIZ,		/* u_int32_t buffer size */
	NFULA_CFG_TIMEOUT,		/* u_int32_t in 1/100 s */
	NFULA_CFG_QTHRESH,		/* u_int32_t */
	NFULA_CFG_FLAGS,		/* u_int16_t */
	__NFULA_CFG_MAX
};
#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1)
@@ -85,4 +88,7 @@ enum nfulnl_attr_config {
#define NFULNL_COPY_META	0x01
#define NFULNL_COPY_PACKET	0x02

#define NFULNL_CFG_F_SEQ	0x0001
#define NFULNL_CFG_F_SEQ_GLOBAL	0x0002

#endif /* _NFNETLINK_LOG_H */
+46 −0
Original line number Diff line number Diff line
@@ -11,6 +11,10 @@
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * 2006-01-26 Harald Welte <laforge@netfilter.org>
 * 	- Add optional local and global sequence number to detect lost
 * 	  events from userspace
 *
 */
#include <linux/module.h>
#include <linux/skbuff.h>
@@ -68,11 +72,14 @@ struct nfulnl_instance {
	unsigned int nlbufsiz;		/* netlink buffer allocation size */
	unsigned int qthreshold;	/* threshold of the queue */
	u_int32_t copy_range;
	u_int32_t seq;			/* instance-local sequential counter */
	u_int16_t group_num;		/* number of this queue */
	u_int16_t flags;
	u_int8_t copy_mode;	
};

static DEFINE_RWLOCK(instances_lock);
static atomic_t global_seq;

#define INSTANCE_BUCKETS	16
static struct hlist_head instance_table[INSTANCE_BUCKETS];
@@ -310,6 +317,16 @@ nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh)
	return 0;
}

static int
nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags)
{
	spin_lock_bh(&inst->lock);
	inst->flags = ntohs(flags);
	spin_unlock_bh(&inst->lock);

	return 0;
}

static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, 
					unsigned int pkt_size)
{
@@ -377,6 +394,8 @@ static void nfulnl_timer(unsigned long data)
	spin_unlock_bh(&inst->lock);
}

/* This is an inline function, we don't really care about a long
 * list of arguments */
static inline int 
__build_packet_message(struct nfulnl_instance *inst,
			const struct sk_buff *skb, 
@@ -515,6 +534,17 @@ __build_packet_message(struct nfulnl_instance *inst,
			read_unlock_bh(&skb->sk->sk_callback_lock);
	}

	/* local sequence number */
	if (inst->flags & NFULNL_CFG_F_SEQ) {
		tmp_uint = htonl(inst->seq++);
		NFA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint);
	}
	/* global sequence number */
	if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) {
		tmp_uint = atomic_inc_return(&global_seq);
		NFA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint);
	}

	if (data_len) {
		struct nfattr *nfa;
		int size = NFA_LENGTH(data_len);
@@ -607,6 +637,11 @@ nfulnl_log_packet(unsigned int pf,

	spin_lock_bh(&inst->lock);

	if (inst->flags & NFULNL_CFG_F_SEQ)
		size += NFA_SPACE(sizeof(u_int32_t));
	if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL)
		size += NFA_SPACE(sizeof(u_int32_t));

	qthreshold = inst->qthreshold;
	/* per-rule qthreshold overrides per-instance */
	if (qthreshold > li->u.ulog.qthreshold)
@@ -736,10 +771,14 @@ static const int nfula_min[NFULA_MAX] = {
	[NFULA_TIMESTAMP-1]	= sizeof(struct nfulnl_msg_packet_timestamp),
	[NFULA_IFINDEX_INDEV-1]	= sizeof(u_int32_t),
	[NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t),
	[NFULA_IFINDEX_PHYSINDEV-1]	= sizeof(u_int32_t),
	[NFULA_IFINDEX_PHYSOUTDEV-1]	= sizeof(u_int32_t),
	[NFULA_HWADDR-1]	= sizeof(struct nfulnl_msg_packet_hw),
	[NFULA_PAYLOAD-1]	= 0,
	[NFULA_PREFIX-1]	= 0,
	[NFULA_UID-1]		= sizeof(u_int32_t),
	[NFULA_SEQ-1]		= sizeof(u_int32_t),
	[NFULA_SEQ_GLOBAL-1]	= sizeof(u_int32_t),
};

static const int nfula_cfg_min[NFULA_CFG_MAX] = {
@@ -748,6 +787,7 @@ static const int nfula_cfg_min[NFULA_CFG_MAX] = {
	[NFULA_CFG_TIMEOUT-1]	= sizeof(u_int32_t),
	[NFULA_CFG_QTHRESH-1]	= sizeof(u_int32_t),
	[NFULA_CFG_NLBUFSIZ-1]	= sizeof(u_int32_t),
	[NFULA_CFG_FLAGS-1]	= sizeof(u_int16_t),
};

static int
@@ -859,6 +899,12 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
		nfulnl_set_qthresh(inst, ntohl(qthresh));
	}

	if (nfula[NFULA_CFG_FLAGS-1]) {
		u_int16_t flags =
			*(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]);
		nfulnl_set_flags(inst, ntohl(flags));
	}

out_put:
	instance_put(inst);
	return ret;