linux/net/netfilter/xt_connbytes.c
<<
>>
Prefs
   1/* Kernel module to match connection tracking byte counter.
   2 * GPL (C) 2002 Martin Devera (devik@cdi.cz).
   3 */
   4#include <linux/module.h>
   5#include <linux/bitops.h>
   6#include <linux/skbuff.h>
   7#include <linux/math64.h>
   8#include <linux/netfilter/x_tables.h>
   9#include <linux/netfilter/xt_connbytes.h>
  10#include <net/netfilter/nf_conntrack.h>
  11#include <net/netfilter/nf_conntrack_acct.h>
  12
  13MODULE_LICENSE("GPL");
  14MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
  15MODULE_DESCRIPTION("Xtables: Number of packets/bytes per connection matching");
  16MODULE_ALIAS("ipt_connbytes");
  17MODULE_ALIAS("ip6t_connbytes");
  18
  19static bool
  20connbytes_mt(const struct sk_buff *skb, const struct xt_match_param *par)
  21{
  22        const struct xt_connbytes_info *sinfo = par->matchinfo;
  23        const struct nf_conn *ct;
  24        enum ip_conntrack_info ctinfo;
  25        u_int64_t what = 0;     /* initialize to make gcc happy */
  26        u_int64_t bytes = 0;
  27        u_int64_t pkts = 0;
  28        const struct nf_conn_counter *counters;
  29
  30        ct = nf_ct_get(skb, &ctinfo);
  31        if (!ct)
  32                return false;
  33
  34        counters = nf_conn_acct_find(ct);
  35        if (!counters)
  36                return false;
  37
  38        switch (sinfo->what) {
  39        case XT_CONNBYTES_PKTS:
  40                switch (sinfo->direction) {
  41                case XT_CONNBYTES_DIR_ORIGINAL:
  42                        what = counters[IP_CT_DIR_ORIGINAL].packets;
  43                        break;
  44                case XT_CONNBYTES_DIR_REPLY:
  45                        what = counters[IP_CT_DIR_REPLY].packets;
  46                        break;
  47                case XT_CONNBYTES_DIR_BOTH:
  48                        what = counters[IP_CT_DIR_ORIGINAL].packets;
  49                        what += counters[IP_CT_DIR_REPLY].packets;
  50                        break;
  51                }
  52                break;
  53        case XT_CONNBYTES_BYTES:
  54                switch (sinfo->direction) {
  55                case XT_CONNBYTES_DIR_ORIGINAL:
  56                        what = counters[IP_CT_DIR_ORIGINAL].bytes;
  57                        break;
  58                case XT_CONNBYTES_DIR_REPLY:
  59                        what = counters[IP_CT_DIR_REPLY].bytes;
  60                        break;
  61                case XT_CONNBYTES_DIR_BOTH:
  62                        what = counters[IP_CT_DIR_ORIGINAL].bytes;
  63                        what += counters[IP_CT_DIR_REPLY].bytes;
  64                        break;
  65                }
  66                break;
  67        case XT_CONNBYTES_AVGPKT:
  68                switch (sinfo->direction) {
  69                case XT_CONNBYTES_DIR_ORIGINAL:
  70                        bytes = counters[IP_CT_DIR_ORIGINAL].bytes;
  71                        pkts  = counters[IP_CT_DIR_ORIGINAL].packets;
  72                        break;
  73                case XT_CONNBYTES_DIR_REPLY:
  74                        bytes = counters[IP_CT_DIR_REPLY].bytes;
  75                        pkts  = counters[IP_CT_DIR_REPLY].packets;
  76                        break;
  77                case XT_CONNBYTES_DIR_BOTH:
  78                        bytes = counters[IP_CT_DIR_ORIGINAL].bytes +
  79                                counters[IP_CT_DIR_REPLY].bytes;
  80                        pkts  = counters[IP_CT_DIR_ORIGINAL].packets +
  81                                counters[IP_CT_DIR_REPLY].packets;
  82                        break;
  83                }
  84                if (pkts != 0)
  85                        what = div64_u64(bytes, pkts);
  86                break;
  87        }
  88
  89        if (sinfo->count.to)
  90                return what <= sinfo->count.to && what >= sinfo->count.from;
  91        else
  92                return what >= sinfo->count.from;
  93}
  94
  95static bool connbytes_mt_check(const struct xt_mtchk_param *par)
  96{
  97        const struct xt_connbytes_info *sinfo = par->matchinfo;
  98
  99        if (sinfo->what != XT_CONNBYTES_PKTS &&
 100            sinfo->what != XT_CONNBYTES_BYTES &&
 101            sinfo->what != XT_CONNBYTES_AVGPKT)
 102                return false;
 103
 104        if (sinfo->direction != XT_CONNBYTES_DIR_ORIGINAL &&
 105            sinfo->direction != XT_CONNBYTES_DIR_REPLY &&
 106            sinfo->direction != XT_CONNBYTES_DIR_BOTH)
 107                return false;
 108
 109        if (nf_ct_l3proto_try_module_get(par->family) < 0) {
 110                printk(KERN_WARNING "can't load conntrack support for "
 111                                    "proto=%u\n", par->family);
 112                return false;
 113        }
 114
 115        return true;
 116}
 117
 118static void connbytes_mt_destroy(const struct xt_mtdtor_param *par)
 119{
 120        nf_ct_l3proto_module_put(par->family);
 121}
 122
 123static struct xt_match connbytes_mt_reg __read_mostly = {
 124        .name       = "connbytes",
 125        .revision   = 0,
 126        .family     = NFPROTO_UNSPEC,
 127        .checkentry = connbytes_mt_check,
 128        .match      = connbytes_mt,
 129        .destroy    = connbytes_mt_destroy,
 130        .matchsize  = sizeof(struct xt_connbytes_info),
 131        .me         = THIS_MODULE,
 132};
 133
 134static int __init connbytes_mt_init(void)
 135{
 136        return xt_register_match(&connbytes_mt_reg);
 137}
 138
 139static void __exit connbytes_mt_exit(void)
 140{
 141        xt_unregister_match(&connbytes_mt_reg);
 142}
 143
 144module_init(connbytes_mt_init);
 145module_exit(connbytes_mt_exit);
 146