root/net/netfilter/xt_connlimit.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. connlimit_mt
  2. connlimit_mt_check
  3. connlimit_mt_destroy
  4. connlimit_mt_init
  5. connlimit_mt_exit

   1 /*
   2  * netfilter module to limit the number of parallel tcp
   3  * connections per IP address.
   4  *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
   5  *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
   6  *              only ignore TIME_WAIT or gone connections
   7  *   (C) CC Computer Consultants GmbH, 2007
   8  *
   9  * based on ...
  10  *
  11  * Kernel module to match connection tracking information.
  12  * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
  13  */
  14 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  15 
  16 #include <linux/ip.h>
  17 #include <linux/ipv6.h>
  18 #include <linux/module.h>
  19 #include <linux/skbuff.h>
  20 #include <linux/netfilter/x_tables.h>
  21 #include <linux/netfilter/xt_connlimit.h>
  22 
  23 #include <net/netfilter/nf_conntrack.h>
  24 #include <net/netfilter/nf_conntrack_core.h>
  25 #include <net/netfilter/nf_conntrack_tuple.h>
  26 #include <net/netfilter/nf_conntrack_zones.h>
  27 #include <net/netfilter/nf_conntrack_count.h>
  28 
  29 static bool
  30 connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
  31 {
  32         struct net *net = xt_net(par);
  33         const struct xt_connlimit_info *info = par->matchinfo;
  34         struct nf_conntrack_tuple tuple;
  35         const struct nf_conntrack_tuple *tuple_ptr = &tuple;
  36         const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
  37         enum ip_conntrack_info ctinfo;
  38         const struct nf_conn *ct;
  39         unsigned int connections;
  40         u32 key[5];
  41 
  42         ct = nf_ct_get(skb, &ctinfo);
  43         if (ct != NULL) {
  44                 tuple_ptr = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
  45                 zone = nf_ct_zone(ct);
  46         } else if (!nf_ct_get_tuplepr(skb, skb_network_offset(skb),
  47                                       xt_family(par), net, &tuple)) {
  48                 goto hotdrop;
  49         }
  50 
  51         if (xt_family(par) == NFPROTO_IPV6) {
  52                 const struct ipv6hdr *iph = ipv6_hdr(skb);
  53                 union nf_inet_addr addr;
  54                 unsigned int i;
  55 
  56                 memcpy(&addr.ip6, (info->flags & XT_CONNLIMIT_DADDR) ?
  57                        &iph->daddr : &iph->saddr, sizeof(addr.ip6));
  58 
  59                 for (i = 0; i < ARRAY_SIZE(addr.ip6); ++i)
  60                         addr.ip6[i] &= info->mask.ip6[i];
  61                 memcpy(key, &addr, sizeof(addr.ip6));
  62                 key[4] = zone->id;
  63         } else {
  64                 const struct iphdr *iph = ip_hdr(skb);
  65                 key[0] = (info->flags & XT_CONNLIMIT_DADDR) ?
  66                           iph->daddr : iph->saddr;
  67 
  68                 key[0] &= info->mask.ip;
  69                 key[1] = zone->id;
  70         }
  71 
  72         connections = nf_conncount_count(net, info->data, key, tuple_ptr,
  73                                          zone);
  74         if (connections == 0)
  75                 /* kmalloc failed, drop it entirely */
  76                 goto hotdrop;
  77 
  78         return (connections > info->limit) ^ !!(info->flags & XT_CONNLIMIT_INVERT);
  79 
  80  hotdrop:
  81         par->hotdrop = true;
  82         return false;
  83 }
  84 
  85 static int connlimit_mt_check(const struct xt_mtchk_param *par)
  86 {
  87         struct xt_connlimit_info *info = par->matchinfo;
  88         unsigned int keylen;
  89 
  90         keylen = sizeof(u32);
  91         if (par->family == NFPROTO_IPV6)
  92                 keylen += sizeof(struct in6_addr);
  93         else
  94                 keylen += sizeof(struct in_addr);
  95 
  96         /* init private data */
  97         info->data = nf_conncount_init(par->net, par->family, keylen);
  98 
  99         return PTR_ERR_OR_ZERO(info->data);
 100 }
 101 
 102 static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
 103 {
 104         const struct xt_connlimit_info *info = par->matchinfo;
 105 
 106         nf_conncount_destroy(par->net, par->family, info->data);
 107 }
 108 
 109 static struct xt_match connlimit_mt_reg __read_mostly = {
 110         .name       = "connlimit",
 111         .revision   = 1,
 112         .family     = NFPROTO_UNSPEC,
 113         .checkentry = connlimit_mt_check,
 114         .match      = connlimit_mt,
 115         .matchsize  = sizeof(struct xt_connlimit_info),
 116         .usersize   = offsetof(struct xt_connlimit_info, data),
 117         .destroy    = connlimit_mt_destroy,
 118         .me         = THIS_MODULE,
 119 };
 120 
 121 static int __init connlimit_mt_init(void)
 122 {
 123         return xt_register_match(&connlimit_mt_reg);
 124 }
 125 
 126 static void __exit connlimit_mt_exit(void)
 127 {
 128         xt_unregister_match(&connlimit_mt_reg);
 129 }
 130 
 131 module_init(connlimit_mt_init);
 132 module_exit(connlimit_mt_exit);
 133 MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
 134 MODULE_DESCRIPTION("Xtables: Number of connections matching");
 135 MODULE_LICENSE("GPL");
 136 MODULE_ALIAS("ipt_connlimit");
 137 MODULE_ALIAS("ip6t_connlimit");

/* [<][>][^][v][top][bottom][index][help] */