diff options
author | Harald Welte <laforge@netfilter.org> | 2006-03-20 20:15:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-20 20:15:11 -0500 |
commit | 0af5f6c1eba4a18e6b2ed518b589927d778c6c16 (patch) | |
tree | ea905a47e7ce2dc2d5076076edc0bf641cf3691c /net | |
parent | 5ee956125a780baf15f2c1d09f2cbf8adcf598fe (diff) |
[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 <laforge@netfilter.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 3b3c781b40c0..54cbbaa712dc 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -11,6 +11,10 @@ | |||
11 | * it under the terms of the GNU General Public License version 2 as | 11 | * it under the terms of the GNU General Public License version 2 as |
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | * | 13 | * |
14 | * 2006-01-26 Harald Welte <laforge@netfilter.org> | ||
15 | * - Add optional local and global sequence number to detect lost | ||
16 | * events from userspace | ||
17 | * | ||
14 | */ | 18 | */ |
15 | #include <linux/module.h> | 19 | #include <linux/module.h> |
16 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
@@ -68,11 +72,14 @@ struct nfulnl_instance { | |||
68 | unsigned int nlbufsiz; /* netlink buffer allocation size */ | 72 | unsigned int nlbufsiz; /* netlink buffer allocation size */ |
69 | unsigned int qthreshold; /* threshold of the queue */ | 73 | unsigned int qthreshold; /* threshold of the queue */ |
70 | u_int32_t copy_range; | 74 | u_int32_t copy_range; |
75 | u_int32_t seq; /* instance-local sequential counter */ | ||
71 | u_int16_t group_num; /* number of this queue */ | 76 | u_int16_t group_num; /* number of this queue */ |
77 | u_int16_t flags; | ||
72 | u_int8_t copy_mode; | 78 | u_int8_t copy_mode; |
73 | }; | 79 | }; |
74 | 80 | ||
75 | static DEFINE_RWLOCK(instances_lock); | 81 | static DEFINE_RWLOCK(instances_lock); |
82 | static atomic_t global_seq; | ||
76 | 83 | ||
77 | #define INSTANCE_BUCKETS 16 | 84 | #define INSTANCE_BUCKETS 16 |
78 | static struct hlist_head instance_table[INSTANCE_BUCKETS]; | 85 | static struct hlist_head instance_table[INSTANCE_BUCKETS]; |
@@ -310,6 +317,16 @@ nfulnl_set_qthresh(struct nfulnl_instance *inst, u_int32_t qthresh) | |||
310 | return 0; | 317 | return 0; |
311 | } | 318 | } |
312 | 319 | ||
320 | static int | ||
321 | nfulnl_set_flags(struct nfulnl_instance *inst, u_int16_t flags) | ||
322 | { | ||
323 | spin_lock_bh(&inst->lock); | ||
324 | inst->flags = ntohs(flags); | ||
325 | spin_unlock_bh(&inst->lock); | ||
326 | |||
327 | return 0; | ||
328 | } | ||
329 | |||
313 | static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, | 330 | static struct sk_buff *nfulnl_alloc_skb(unsigned int inst_size, |
314 | unsigned int pkt_size) | 331 | unsigned int pkt_size) |
315 | { | 332 | { |
@@ -377,6 +394,8 @@ static void nfulnl_timer(unsigned long data) | |||
377 | spin_unlock_bh(&inst->lock); | 394 | spin_unlock_bh(&inst->lock); |
378 | } | 395 | } |
379 | 396 | ||
397 | /* This is an inline function, we don't really care about a long | ||
398 | * list of arguments */ | ||
380 | static inline int | 399 | static inline int |
381 | __build_packet_message(struct nfulnl_instance *inst, | 400 | __build_packet_message(struct nfulnl_instance *inst, |
382 | const struct sk_buff *skb, | 401 | const struct sk_buff *skb, |
@@ -515,6 +534,17 @@ __build_packet_message(struct nfulnl_instance *inst, | |||
515 | read_unlock_bh(&skb->sk->sk_callback_lock); | 534 | read_unlock_bh(&skb->sk->sk_callback_lock); |
516 | } | 535 | } |
517 | 536 | ||
537 | /* local sequence number */ | ||
538 | if (inst->flags & NFULNL_CFG_F_SEQ) { | ||
539 | tmp_uint = htonl(inst->seq++); | ||
540 | NFA_PUT(inst->skb, NFULA_SEQ, sizeof(tmp_uint), &tmp_uint); | ||
541 | } | ||
542 | /* global sequence number */ | ||
543 | if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) { | ||
544 | tmp_uint = atomic_inc_return(&global_seq); | ||
545 | NFA_PUT(inst->skb, NFULA_SEQ_GLOBAL, sizeof(tmp_uint), &tmp_uint); | ||
546 | } | ||
547 | |||
518 | if (data_len) { | 548 | if (data_len) { |
519 | struct nfattr *nfa; | 549 | struct nfattr *nfa; |
520 | int size = NFA_LENGTH(data_len); | 550 | int size = NFA_LENGTH(data_len); |
@@ -607,6 +637,11 @@ nfulnl_log_packet(unsigned int pf, | |||
607 | 637 | ||
608 | spin_lock_bh(&inst->lock); | 638 | spin_lock_bh(&inst->lock); |
609 | 639 | ||
640 | if (inst->flags & NFULNL_CFG_F_SEQ) | ||
641 | size += NFA_SPACE(sizeof(u_int32_t)); | ||
642 | if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) | ||
643 | size += NFA_SPACE(sizeof(u_int32_t)); | ||
644 | |||
610 | qthreshold = inst->qthreshold; | 645 | qthreshold = inst->qthreshold; |
611 | /* per-rule qthreshold overrides per-instance */ | 646 | /* per-rule qthreshold overrides per-instance */ |
612 | if (qthreshold > li->u.ulog.qthreshold) | 647 | if (qthreshold > li->u.ulog.qthreshold) |
@@ -736,10 +771,14 @@ static const int nfula_min[NFULA_MAX] = { | |||
736 | [NFULA_TIMESTAMP-1] = sizeof(struct nfulnl_msg_packet_timestamp), | 771 | [NFULA_TIMESTAMP-1] = sizeof(struct nfulnl_msg_packet_timestamp), |
737 | [NFULA_IFINDEX_INDEV-1] = sizeof(u_int32_t), | 772 | [NFULA_IFINDEX_INDEV-1] = sizeof(u_int32_t), |
738 | [NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t), | 773 | [NFULA_IFINDEX_OUTDEV-1]= sizeof(u_int32_t), |
774 | [NFULA_IFINDEX_PHYSINDEV-1] = sizeof(u_int32_t), | ||
775 | [NFULA_IFINDEX_PHYSOUTDEV-1] = sizeof(u_int32_t), | ||
739 | [NFULA_HWADDR-1] = sizeof(struct nfulnl_msg_packet_hw), | 776 | [NFULA_HWADDR-1] = sizeof(struct nfulnl_msg_packet_hw), |
740 | [NFULA_PAYLOAD-1] = 0, | 777 | [NFULA_PAYLOAD-1] = 0, |
741 | [NFULA_PREFIX-1] = 0, | 778 | [NFULA_PREFIX-1] = 0, |
742 | [NFULA_UID-1] = sizeof(u_int32_t), | 779 | [NFULA_UID-1] = sizeof(u_int32_t), |
780 | [NFULA_SEQ-1] = sizeof(u_int32_t), | ||
781 | [NFULA_SEQ_GLOBAL-1] = sizeof(u_int32_t), | ||
743 | }; | 782 | }; |
744 | 783 | ||
745 | static const int nfula_cfg_min[NFULA_CFG_MAX] = { | 784 | static const int nfula_cfg_min[NFULA_CFG_MAX] = { |
@@ -748,6 +787,7 @@ static const int nfula_cfg_min[NFULA_CFG_MAX] = { | |||
748 | [NFULA_CFG_TIMEOUT-1] = sizeof(u_int32_t), | 787 | [NFULA_CFG_TIMEOUT-1] = sizeof(u_int32_t), |
749 | [NFULA_CFG_QTHRESH-1] = sizeof(u_int32_t), | 788 | [NFULA_CFG_QTHRESH-1] = sizeof(u_int32_t), |
750 | [NFULA_CFG_NLBUFSIZ-1] = sizeof(u_int32_t), | 789 | [NFULA_CFG_NLBUFSIZ-1] = sizeof(u_int32_t), |
790 | [NFULA_CFG_FLAGS-1] = sizeof(u_int16_t), | ||
751 | }; | 791 | }; |
752 | 792 | ||
753 | static int | 793 | static int |
@@ -859,6 +899,12 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
859 | nfulnl_set_qthresh(inst, ntohl(qthresh)); | 899 | nfulnl_set_qthresh(inst, ntohl(qthresh)); |
860 | } | 900 | } |
861 | 901 | ||
902 | if (nfula[NFULA_CFG_FLAGS-1]) { | ||
903 | u_int16_t flags = | ||
904 | *(u_int16_t *)NFA_DATA(nfula[NFULA_CFG_FLAGS-1]); | ||
905 | nfulnl_set_flags(inst, ntohl(flags)); | ||
906 | } | ||
907 | |||
862 | out_put: | 908 | out_put: |
863 | instance_put(inst); | 909 | instance_put(inst); |
864 | return ret; | 910 | return ret; |