0001
0002
0003
0004 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0005 #include <linux/module.h>
0006 #include <linux/bitops.h>
0007 #include <linux/skbuff.h>
0008 #include <linux/math64.h>
0009 #include <linux/netfilter/x_tables.h>
0010 #include <linux/netfilter/xt_connbytes.h>
0011 #include <net/netfilter/nf_conntrack.h>
0012 #include <net/netfilter/nf_conntrack_acct.h>
0013
0014 MODULE_LICENSE("GPL");
0015 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
0016 MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
0017 MODULE_ALIAS("ipt_connbytes");
0018 MODULE_ALIAS("ip6t_connbytes");
0019
0020 static bool
0021 connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par)
0022 {
0023 const struct xt_connbytes_info *sinfo = par->matchinfo;
0024 const struct nf_conn *ct;
0025 enum ip_conntrack_info ctinfo;
0026 u_int64_t what = 0;
0027 u_int64_t bytes = 0;
0028 u_int64_t pkts = 0;
0029 const struct nf_conn_acct *acct;
0030 const struct nf_conn_counter *counters;
0031
0032 ct = nf_ct_get(skb, &ctinfo);
0033 if (!ct)
0034 return false;
0035
0036 acct = nf_conn_acct_find(ct);
0037 if (!acct)
0038 return false;
0039
0040 counters = acct->counter;
0041 switch (sinfo->what) {
0042 case XT_CONNBYTES_PKTS:
0043 switch (sinfo->direction) {
0044 case XT_CONNBYTES_DIR_ORIGINAL:
0045 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
0046 break;
0047 case XT_CONNBYTES_DIR_REPLY:
0048 what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
0049 break;
0050 case XT_CONNBYTES_DIR_BOTH:
0051 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
0052 what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
0053 break;
0054 }
0055 break;
0056 case XT_CONNBYTES_BYTES:
0057 switch (sinfo->direction) {
0058 case XT_CONNBYTES_DIR_ORIGINAL:
0059 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
0060 break;
0061 case XT_CONNBYTES_DIR_REPLY:
0062 what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
0063 break;
0064 case XT_CONNBYTES_DIR_BOTH:
0065 what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
0066 what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
0067 break;
0068 }
0069 break;
0070 case XT_CONNBYTES_AVGPKT:
0071 switch (sinfo->direction) {
0072 case XT_CONNBYTES_DIR_ORIGINAL:
0073 bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes);
0074 pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets);
0075 break;
0076 case XT_CONNBYTES_DIR_REPLY:
0077 bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
0078 pkts = atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
0079 break;
0080 case XT_CONNBYTES_DIR_BOTH:
0081 bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes) +
0082 atomic64_read(&counters[IP_CT_DIR_REPLY].bytes);
0083 pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets) +
0084 atomic64_read(&counters[IP_CT_DIR_REPLY].packets);
0085 break;
0086 }
0087 if (pkts != 0)
0088 what = div64_u64(bytes, pkts);
0089 break;
0090 }
0091
0092 if (sinfo->count.to >= sinfo->count.from)
0093 return what <= sinfo->count.to && what >= sinfo->count.from;
0094 else
0095 return what < sinfo->count.to || what > sinfo->count.from;
0096 }
0097
0098 static int connbytes_mt_check(const struct xt_mtchk_param *par)
0099 {
0100 const struct xt_connbytes_info *sinfo = par->matchinfo;
0101 int ret;
0102
0103 if (sinfo->what != XT_CONNBYTES_PKTS &&
0104 sinfo->what != XT_CONNBYTES_BYTES &&
0105 sinfo->what != XT_CONNBYTES_AVGPKT)
0106 return -EINVAL;
0107
0108 if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
0109 sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
0110 sinfo->direction != XT_CONNBYTES_DIR_BOTH)
0111 return -EINVAL;
0112
0113 ret = nf_ct_netns_get(par->net, par->family);
0114 if (ret < 0)
0115 pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
0116 par->family);
0117
0118
0119
0120
0121
0122 if (!nf_ct_acct_enabled(par->net)) {
0123 pr_warn("Forcing CT accounting to be enabled\n");
0124 nf_ct_set_acct(par->net, true);
0125 }
0126
0127 return ret;
0128 }
0129
0130 static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)
0131 {
0132 nf_ct_netns_put(par->net, par->family);
0133 }
0134
0135 static struct xt_match connbytes_mt_reg __read_mostly = {
0136 .name = "connbytes",
0137 .revision = 0,
0138 .family = NFPROTO_UNSPEC,
0139 .checkentry = connbytes_mt_check,
0140 .match = connbytes_mt,
0141 .destroy = connbytes_mt_destroy,
0142 .matchsize = sizeof(struct xt_connbytes_info),
0143 .me = THIS_MODULE,
0144 };
0145
0146 static int __init connbytes_mt_init(void)
0147 {
0148 return xt_register_match(&connbytes_mt_reg);
0149 }
0150
0151 static void __exit connbytes_mt_exit(void)
0152 {
0153 xt_unregister_match(&connbytes_mt_reg);
0154 }
0155
0156 module_init(connbytes_mt_init);
0157 module_exit(connbytes_mt_exit);