diff options
-rw-r--r-- | include/linux/netfilter/nfnetlink_log.h | 6 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 46 |
2 files changed, 52 insertions, 0 deletions
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h index b04b03880595..a7497c7436df 100644 --- a/include/linux/netfilter/nfnetlink_log.h +++ b/include/linux/netfilter/nfnetlink_log.h | |||
@@ -47,6 +47,8 @@ enum nfulnl_attr_type { | |||
47 | NFULA_PAYLOAD, /* opaque data payload */ | 47 | NFULA_PAYLOAD, /* opaque data payload */ |
48 | NFULA_PREFIX, /* string prefix */ | 48 | NFULA_PREFIX, /* string prefix */ |
49 | NFULA_UID, /* user id of socket */ | 49 | NFULA_UID, /* user id of socket */ |
50 | NFULA_SEQ, /* instance-local sequence number */ | ||
51 | NFULA_SEQ_GLOBAL, /* global sequence number */ | ||
50 | 52 | ||
51 | __NFULA_MAX | 53 | __NFULA_MAX |
52 | }; | 54 | }; |
@@ -77,6 +79,7 @@ enum nfulnl_attr_config { | |||
77 | NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */ | 79 | NFULA_CFG_NLBUFSIZ, /* u_int32_t buffer size */ |
78 | NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */ | 80 | NFULA_CFG_TIMEOUT, /* u_int32_t in 1/100 s */ |
79 | NFULA_CFG_QTHRESH, /* u_int32_t */ | 81 | NFULA_CFG_QTHRESH, /* u_int32_t */ |
82 | NFULA_CFG_FLAGS, /* u_int16_t */ | ||
80 | __NFULA_CFG_MAX | 83 | __NFULA_CFG_MAX |
81 | }; | 84 | }; |
82 | #define NFULA_CFG_MAX (__NFULA_CFG_MAX -1) | 85 | #define NFULA_CFG_MAX (__NFULA_CFG_MAX -1) |
@@ -85,4 +88,7 @@ enum nfulnl_attr_config { | |||
85 | #define NFULNL_COPY_META 0x01 | 88 | #define NFULNL_COPY_META 0x01 |
86 | #define NFULNL_COPY_PACKET 0x02 | 89 | #define NFULNL_COPY_PACKET 0x02 |
87 | 90 | ||
91 | #define NFULNL_CFG_F_SEQ 0x0001 | ||
92 | #define NFULNL_CFG_F_SEQ_GLOBAL 0x0002 | ||
93 | |||
88 | #endif /* _NFNETLINK_LOG_H */ | 94 | #endif /* _NFNETLINK_LOG_H */ |
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; |