diff options
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 84 |
1 files changed, 39 insertions, 45 deletions
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 4f9c941335c9..85033344aed2 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -203,25 +203,18 @@ nla_put_failure: | |||
203 | } | 203 | } |
204 | 204 | ||
205 | static int | 205 | static int |
206 | ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, | 206 | dump_counters(struct sk_buff *skb, u64 pkts, u64 bytes, |
207 | enum ip_conntrack_dir dir) | 207 | enum ip_conntrack_dir dir) |
208 | { | 208 | { |
209 | enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; | 209 | enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; |
210 | struct nlattr *nest_count; | 210 | struct nlattr *nest_count; |
211 | const struct nf_conn_counter *acct; | ||
212 | |||
213 | acct = nf_conn_acct_find(ct); | ||
214 | if (!acct) | ||
215 | return 0; | ||
216 | 211 | ||
217 | nest_count = nla_nest_start(skb, type | NLA_F_NESTED); | 212 | nest_count = nla_nest_start(skb, type | NLA_F_NESTED); |
218 | if (!nest_count) | 213 | if (!nest_count) |
219 | goto nla_put_failure; | 214 | goto nla_put_failure; |
220 | 215 | ||
221 | NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, | 216 | NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts)); |
222 | cpu_to_be64(atomic64_read(&acct[dir].packets))); | 217 | NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes)); |
223 | NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, | ||
224 | cpu_to_be64(atomic64_read(&acct[dir].bytes))); | ||
225 | 218 | ||
226 | nla_nest_end(skb, nest_count); | 219 | nla_nest_end(skb, nest_count); |
227 | 220 | ||
@@ -232,6 +225,27 @@ nla_put_failure: | |||
232 | } | 225 | } |
233 | 226 | ||
234 | static int | 227 | static int |
228 | ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, | ||
229 | enum ip_conntrack_dir dir, int type) | ||
230 | { | ||
231 | struct nf_conn_counter *acct; | ||
232 | u64 pkts, bytes; | ||
233 | |||
234 | acct = nf_conn_acct_find(ct); | ||
235 | if (!acct) | ||
236 | return 0; | ||
237 | |||
238 | if (type == IPCTNL_MSG_CT_GET_CTRZERO) { | ||
239 | pkts = atomic64_xchg(&acct[dir].packets, 0); | ||
240 | bytes = atomic64_xchg(&acct[dir].bytes, 0); | ||
241 | } else { | ||
242 | pkts = atomic64_read(&acct[dir].packets); | ||
243 | bytes = atomic64_read(&acct[dir].bytes); | ||
244 | } | ||
245 | return dump_counters(skb, pkts, bytes, dir); | ||
246 | } | ||
247 | |||
248 | static int | ||
235 | ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) | 249 | ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) |
236 | { | 250 | { |
237 | struct nlattr *nest_count; | 251 | struct nlattr *nest_count; |
@@ -393,15 +407,15 @@ nla_put_failure: | |||
393 | } | 407 | } |
394 | 408 | ||
395 | static int | 409 | static int |
396 | ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | 410 | ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, |
397 | int event, struct nf_conn *ct) | 411 | struct nf_conn *ct) |
398 | { | 412 | { |
399 | struct nlmsghdr *nlh; | 413 | struct nlmsghdr *nlh; |
400 | struct nfgenmsg *nfmsg; | 414 | struct nfgenmsg *nfmsg; |
401 | struct nlattr *nest_parms; | 415 | struct nlattr *nest_parms; |
402 | unsigned int flags = pid ? NLM_F_MULTI : 0; | 416 | unsigned int flags = pid ? NLM_F_MULTI : 0, event; |
403 | 417 | ||
404 | event |= NFNL_SUBSYS_CTNETLINK << 8; | 418 | event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW); |
405 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | 419 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); |
406 | if (nlh == NULL) | 420 | if (nlh == NULL) |
407 | goto nlmsg_failure; | 421 | goto nlmsg_failure; |
@@ -430,8 +444,8 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | |||
430 | 444 | ||
431 | if (ctnetlink_dump_status(skb, ct) < 0 || | 445 | if (ctnetlink_dump_status(skb, ct) < 0 || |
432 | ctnetlink_dump_timeout(skb, ct) < 0 || | 446 | ctnetlink_dump_timeout(skb, ct) < 0 || |
433 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || | 447 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL, type) < 0 || |
434 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 || | 448 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY, type) < 0 || |
435 | ctnetlink_dump_timestamp(skb, ct) < 0 || | 449 | ctnetlink_dump_timestamp(skb, ct) < 0 || |
436 | ctnetlink_dump_protoinfo(skb, ct) < 0 || | 450 | ctnetlink_dump_protoinfo(skb, ct) < 0 || |
437 | ctnetlink_dump_helpinfo(skb, ct) < 0 || | 451 | ctnetlink_dump_helpinfo(skb, ct) < 0 || |
@@ -612,8 +626,10 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) | |||
612 | goto nla_put_failure; | 626 | goto nla_put_failure; |
613 | 627 | ||
614 | if (events & (1 << IPCT_DESTROY)) { | 628 | if (events & (1 << IPCT_DESTROY)) { |
615 | if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || | 629 | if (ctnetlink_dump_counters(skb, ct, |
616 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 || | 630 | IP_CT_DIR_ORIGINAL, type) < 0 || |
631 | ctnetlink_dump_counters(skb, ct, | ||
632 | IP_CT_DIR_REPLY, type) < 0 || | ||
617 | ctnetlink_dump_timestamp(skb, ct) < 0) | 633 | ctnetlink_dump_timestamp(skb, ct) < 0) |
618 | goto nla_put_failure; | 634 | goto nla_put_failure; |
619 | } else { | 635 | } else { |
@@ -709,24 +725,13 @@ restart: | |||
709 | } | 725 | } |
710 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, | 726 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, |
711 | cb->nlh->nlmsg_seq, | 727 | cb->nlh->nlmsg_seq, |
712 | IPCTNL_MSG_CT_NEW, ct) < 0) { | 728 | NFNL_MSG_TYPE( |
729 | cb->nlh->nlmsg_type), | ||
730 | ct) < 0) { | ||
713 | nf_conntrack_get(&ct->ct_general); | 731 | nf_conntrack_get(&ct->ct_general); |
714 | cb->args[1] = (unsigned long)ct; | 732 | cb->args[1] = (unsigned long)ct; |
715 | goto out; | 733 | goto out; |
716 | } | 734 | } |
717 | |||
718 | if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == | ||
719 | IPCTNL_MSG_CT_GET_CTRZERO) { | ||
720 | struct nf_conn_counter *acct; | ||
721 | |||
722 | acct = nf_conn_acct_find(ct); | ||
723 | if (acct) { | ||
724 | atomic64_set(&acct[IP_CT_DIR_ORIGINAL].bytes, 0); | ||
725 | atomic64_set(&acct[IP_CT_DIR_ORIGINAL].packets, 0); | ||
726 | atomic64_set(&acct[IP_CT_DIR_REPLY].bytes, 0); | ||
727 | atomic64_set(&acct[IP_CT_DIR_REPLY].packets, 0); | ||
728 | } | ||
729 | } | ||
730 | } | 735 | } |
731 | if (cb->args[1]) { | 736 | if (cb->args[1]) { |
732 | cb->args[1] = 0; | 737 | cb->args[1] = 0; |
@@ -1005,7 +1010,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1005 | 1010 | ||
1006 | rcu_read_lock(); | 1011 | rcu_read_lock(); |
1007 | err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, | 1012 | err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, |
1008 | IPCTNL_MSG_CT_NEW, ct); | 1013 | NFNL_MSG_TYPE(nlh->nlmsg_type), ct); |
1009 | rcu_read_unlock(); | 1014 | rcu_read_unlock(); |
1010 | nf_ct_put(ct); | 1015 | nf_ct_put(ct); |
1011 | if (err <= 0) | 1016 | if (err <= 0) |
@@ -1015,17 +1020,6 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
1015 | if (err < 0) | 1020 | if (err < 0) |
1016 | goto out; | 1021 | goto out; |
1017 | 1022 | ||
1018 | if (NFNL_MSG_TYPE(nlh->nlmsg_type) == IPCTNL_MSG_CT_GET_CTRZERO) { | ||
1019 | struct nf_conn_counter *acct; | ||
1020 | |||
1021 | acct = nf_conn_acct_find(ct); | ||
1022 | if (acct) { | ||
1023 | atomic64_set(&acct[IP_CT_DIR_ORIGINAL].bytes, 0); | ||
1024 | atomic64_set(&acct[IP_CT_DIR_ORIGINAL].packets, 0); | ||
1025 | atomic64_set(&acct[IP_CT_DIR_REPLY].bytes, 0); | ||
1026 | atomic64_set(&acct[IP_CT_DIR_REPLY].packets, 0); | ||
1027 | } | ||
1028 | } | ||
1029 | return 0; | 1023 | return 0; |
1030 | 1024 | ||
1031 | free: | 1025 | free: |