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