Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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