xt_connbytes.c 4.1 KB

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