nf_conntrack_acct.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /* Accouting handling for netfilter. */
  2. /*
  3. * (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/netfilter.h>
  10. #include <linux/slab.h>
  11. #include <linux/kernel.h>
  12. #include <linux/moduleparam.h>
  13. #include <linux/export.h>
  14. #include <net/netfilter/nf_conntrack.h>
  15. #include <net/netfilter/nf_conntrack_extend.h>
  16. #include <net/netfilter/nf_conntrack_acct.h>
  17. static bool nf_ct_acct __read_mostly;
  18. module_param_named(acct, nf_ct_acct, bool, 0644);
  19. MODULE_PARM_DESC(acct, "Enable connection tracking flow accounting.");
  20. #ifdef CONFIG_SYSCTL
  21. static struct ctl_table acct_sysctl_table[] = {
  22. {
  23. .procname = "nf_conntrack_acct",
  24. .data = &init_net.ct.sysctl_acct,
  25. .maxlen = sizeof(unsigned int),
  26. .mode = 0644,
  27. .proc_handler = proc_dointvec,
  28. },
  29. {}
  30. };
  31. #endif /* CONFIG_SYSCTL */
  32. unsigned int
  33. seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir)
  34. {
  35. struct nf_conn_acct *acct;
  36. struct nf_conn_counter *counter;
  37. acct = nf_conn_acct_find(ct);
  38. if (!acct)
  39. return 0;
  40. counter = acct->counter;
  41. seq_printf(s, "packets=%llu bytes=%llu ",
  42. (unsigned long long)atomic64_read(&counter[dir].packets),
  43. (unsigned long long)atomic64_read(&counter[dir].bytes));
  44. return 0;
  45. };
  46. EXPORT_SYMBOL_GPL(seq_print_acct);
  47. static struct nf_ct_ext_type acct_extend __read_mostly = {
  48. .len = sizeof(struct nf_conn_acct),
  49. .align = __alignof__(struct nf_conn_acct),
  50. .id = NF_CT_EXT_ACCT,
  51. };
  52. #ifdef CONFIG_SYSCTL
  53. static int nf_conntrack_acct_init_sysctl(struct net *net)
  54. {
  55. struct ctl_table *table;
  56. table = kmemdup(acct_sysctl_table, sizeof(acct_sysctl_table),
  57. GFP_KERNEL);
  58. if (!table)
  59. goto out;
  60. table[0].data = &net->ct.sysctl_acct;
  61. /* Don't export sysctls to unprivileged users */
  62. if (net->user_ns != &init_user_ns)
  63. table[0].procname = NULL;
  64. net->ct.acct_sysctl_header = register_net_sysctl(net, "net/netfilter",
  65. table);
  66. if (!net->ct.acct_sysctl_header) {
  67. printk(KERN_ERR "nf_conntrack_acct: can't register to sysctl.\n");
  68. goto out_register;
  69. }
  70. return 0;
  71. out_register:
  72. kfree(table);
  73. out:
  74. return -ENOMEM;
  75. }
  76. static void nf_conntrack_acct_fini_sysctl(struct net *net)
  77. {
  78. struct ctl_table *table;
  79. table = net->ct.acct_sysctl_header->ctl_table_arg;
  80. unregister_net_sysctl_table(net->ct.acct_sysctl_header);
  81. kfree(table);
  82. }
  83. #else
  84. static int nf_conntrack_acct_init_sysctl(struct net *net)
  85. {
  86. return 0;
  87. }
  88. static void nf_conntrack_acct_fini_sysctl(struct net *net)
  89. {
  90. }
  91. #endif
  92. int nf_conntrack_acct_pernet_init(struct net *net)
  93. {
  94. net->ct.sysctl_acct = nf_ct_acct;
  95. return nf_conntrack_acct_init_sysctl(net);
  96. }
  97. void nf_conntrack_acct_pernet_fini(struct net *net)
  98. {
  99. nf_conntrack_acct_fini_sysctl(net);
  100. }
  101. int nf_conntrack_acct_init(void)
  102. {
  103. int ret = nf_ct_extend_register(&acct_extend);
  104. if (ret < 0)
  105. pr_err("nf_conntrack_acct: Unable to register extension\n");
  106. return ret;
  107. }
  108. void nf_conntrack_acct_fini(void)
  109. {
  110. nf_ct_extend_unregister(&acct_extend);
  111. }