From 0af5f6c1eba4a18e6b2ed518b589927d778c6c16 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 20 Mar 2006 17:15:11 -0800 Subject: [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: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink_log.h | 6 +++++ net/netfilter/nfnetlink_log.c | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index b04b038..a7497c7 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h @@ -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 */ diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 3b3c781..54cbbaa 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -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 + * - Add optional local and global sequence number to detect lost + * events from userspace + * */ #include #include @@ -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; -- cgit v1.1