aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVishwanath Pai <vpai@akamai.com>2016-09-22 12:43:44 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2016-09-25 08:54:06 -0400
commit11d5f15723c9f39d7c131d0149d024c17dbef676 (patch)
tree25daeeeaca4387aff480c28548039adb60c21d8f /net
parent0dc60a4546fefc6dc9f54abf60beeeb3501726fa (diff)
netfilter: xt_hashlimit: Create revision 2 to support higher pps rates
Create a new revision for the hashlimit iptables extension module. Rev 2 will support higher pps of upto 1 million, Version 1 supports only 10k. To support this we have to increase the size of the variables avg and burst in hashlimit_cfg to 64-bit. Create two new structs hashlimit_cfg2 and xt_hashlimit_mtinfo2 and also create newer versions of all the functions for match, checkentry and destroy. Some of the functions like hashlimit_mt, hashlimit_mt_check etc are very similar in both rev1 and rev2 with only minor changes, so I have split those functions and moved all the common code to a *_common function. Signed-off-by: Vishwanath Pai <vpai@akamai.com> Signed-off-by: Joshua Hunt <johunt@akamai.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/xt_hashlimit.c330
1 files changed, 262 insertions, 68 deletions
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index e93d9e0a3f35..44a095ecc7b7 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -57,6 +57,7 @@ static inline struct hashlimit_net *hashlimit_pernet(struct net *net)
57 57
58/* need to declare this at the top */ 58/* need to declare this at the top */
59static const struct file_operations dl_file_ops_v1; 59static const struct file_operations dl_file_ops_v1;
60static const struct file_operations dl_file_ops;
60 61
61/* hash table crap */ 62/* hash table crap */
62struct dsthash_dst { 63struct dsthash_dst {
@@ -86,8 +87,8 @@ struct dsthash_ent {
86 unsigned long expires; /* precalculated expiry time */ 87 unsigned long expires; /* precalculated expiry time */
87 struct { 88 struct {
88 unsigned long prev; /* last modification */ 89 unsigned long prev; /* last modification */
89 u_int32_t credit; 90 u_int64_t credit;
90 u_int32_t credit_cap, cost; 91 u_int64_t credit_cap, cost;
91 } rateinfo; 92 } rateinfo;
92 struct rcu_head rcu; 93 struct rcu_head rcu;
93}; 94};
@@ -98,7 +99,7 @@ struct xt_hashlimit_htable {
98 u_int8_t family; 99 u_int8_t family;
99 bool rnd_initialized; 100 bool rnd_initialized;
100 101
101 struct hashlimit_cfg1 cfg; /* config */ 102 struct hashlimit_cfg2 cfg; /* config */
102 103
103 /* used internally */ 104 /* used internally */
104 spinlock_t lock; /* lock for list_head */ 105 spinlock_t lock; /* lock for list_head */
@@ -114,6 +115,30 @@ struct xt_hashlimit_htable {
114 struct hlist_head hash[0]; /* hashtable itself */ 115 struct hlist_head hash[0]; /* hashtable itself */
115}; 116};
116 117
118static int
119cfg_copy(struct hashlimit_cfg2 *to, void *from, int revision)
120{
121 if (revision == 1) {
122 struct hashlimit_cfg1 *cfg = (struct hashlimit_cfg1 *)from;
123
124 to->mode = cfg->mode;
125 to->avg = cfg->avg;
126 to->burst = cfg->burst;
127 to->size = cfg->size;
128 to->max = cfg->max;
129 to->gc_interval = cfg->gc_interval;
130 to->expire = cfg->expire;
131 to->srcmask = cfg->srcmask;
132 to->dstmask = cfg->dstmask;
133 } else if (revision == 2) {
134 memcpy(to, from, sizeof(struct hashlimit_cfg2));
135 } else {
136 return -EINVAL;
137 }
138
139 return 0;
140}
141
117static DEFINE_MUTEX(hashlimit_mutex); /* protects htables list */ 142static DEFINE_MUTEX(hashlimit_mutex); /* protects htables list */
118static struct kmem_cache *hashlimit_cachep __read_mostly; 143static struct kmem_cache *hashlimit_cachep __read_mostly;
119 144
@@ -215,16 +240,18 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent)
215} 240}
216static void htable_gc(struct work_struct *work); 241static void htable_gc(struct work_struct *work);
217 242
218static int htable_create_v1(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, 243static int htable_create(struct net *net, struct hashlimit_cfg2 *cfg,
219 u_int8_t family) 244 const char *name, u_int8_t family,
245 struct xt_hashlimit_htable **out_hinfo,
246 int revision)
220{ 247{
221 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); 248 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
222 struct xt_hashlimit_htable *hinfo; 249 struct xt_hashlimit_htable *hinfo;
223 unsigned int size; 250 unsigned int size, i;
224 unsigned int i; 251 int ret;
225 252
226 if (minfo->cfg.size) { 253 if (cfg->size) {
227 size = minfo->cfg.size; 254 size = cfg->size;
228 } else { 255 } else {
229 size = (totalram_pages << PAGE_SHIFT) / 16384 / 256 size = (totalram_pages << PAGE_SHIFT) / 16384 /
230 sizeof(struct list_head); 257 sizeof(struct list_head);
@@ -238,10 +265,14 @@ static int htable_create_v1(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
238 sizeof(struct list_head) * size); 265 sizeof(struct list_head) * size);
239 if (hinfo == NULL) 266 if (hinfo == NULL)
240 return -ENOMEM; 267 return -ENOMEM;
241 minfo->hinfo = hinfo; 268 *out_hinfo = hinfo;
242 269
243 /* copy match config into hashtable config */ 270 /* copy match config into hashtable config */
244 memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg)); 271 ret = cfg_copy(&hinfo->cfg, (void *)cfg, 2);
272
273 if (ret)
274 return ret;
275
245 hinfo->cfg.size = size; 276 hinfo->cfg.size = size;
246 if (hinfo->cfg.max == 0) 277 if (hinfo->cfg.max == 0)
247 hinfo->cfg.max = 8 * hinfo->cfg.size; 278 hinfo->cfg.max = 8 * hinfo->cfg.size;
@@ -255,17 +286,18 @@ static int htable_create_v1(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
255 hinfo->count = 0; 286 hinfo->count = 0;
256 hinfo->family = family; 287 hinfo->family = family;
257 hinfo->rnd_initialized = false; 288 hinfo->rnd_initialized = false;
258 hinfo->name = kstrdup(minfo->name, GFP_KERNEL); 289 hinfo->name = kstrdup(name, GFP_KERNEL);
259 if (!hinfo->name) { 290 if (!hinfo->name) {
260 vfree(hinfo); 291 vfree(hinfo);
261 return -ENOMEM; 292 return -ENOMEM;
262 } 293 }
263 spin_lock_init(&hinfo->lock); 294 spin_lock_init(&hinfo->lock);
264 295
265 hinfo->pde = proc_create_data(minfo->name, 0, 296 hinfo->pde = proc_create_data(name, 0,
266 (family == NFPROTO_IPV4) ? 297 (family == NFPROTO_IPV4) ?
267 hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit, 298 hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit,
268 &dl_file_ops_v1, hinfo); 299 (revision == 1) ? &dl_file_ops_v1 : &dl_file_ops,
300 hinfo);
269 if (hinfo->pde == NULL) { 301 if (hinfo->pde == NULL) {
270 kfree(hinfo->name); 302 kfree(hinfo->name);
271 vfree(hinfo); 303 vfree(hinfo);
@@ -399,6 +431,7 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
399 CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie. 431 CREDITS_PER_JIFFY*HZ*60*60*24 < 2^32 ie.
400*/ 432*/
401#define MAX_CPJ_v1 (0xFFFFFFFF / (HZ*60*60*24)) 433#define MAX_CPJ_v1 (0xFFFFFFFF / (HZ*60*60*24))
434#define MAX_CPJ (0xFFFFFFFFFFFFFFFF / (HZ*60*60*24))
402 435
403/* Repeated shift and or gives us all 1s, final shift and add 1 gives 436/* Repeated shift and or gives us all 1s, final shift and add 1 gives
404 * us the power of 2 below the theoretical max, so GCC simply does a 437 * us the power of 2 below the theoretical max, so GCC simply does a
@@ -408,8 +441,11 @@ static void htable_put(struct xt_hashlimit_htable *hinfo)
408#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4)) 441#define _POW2_BELOW8(x) (_POW2_BELOW4(x)|_POW2_BELOW4((x)>>4))
409#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8)) 442#define _POW2_BELOW16(x) (_POW2_BELOW8(x)|_POW2_BELOW8((x)>>8))
410#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16)) 443#define _POW2_BELOW32(x) (_POW2_BELOW16(x)|_POW2_BELOW16((x)>>16))
444#define _POW2_BELOW64(x) (_POW2_BELOW32(x)|_POW2_BELOW32((x)>>32))
411#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1) 445#define POW2_BELOW32(x) ((_POW2_BELOW32(x)>>1) + 1)
446#define POW2_BELOW64(x) ((_POW2_BELOW64(x)>>1) + 1)
412 447
448#define CREDITS_PER_JIFFY POW2_BELOW64(MAX_CPJ)
413#define CREDITS_PER_JIFFY_v1 POW2_BELOW32(MAX_CPJ_v1) 449#define CREDITS_PER_JIFFY_v1 POW2_BELOW32(MAX_CPJ_v1)
414 450
415/* in byte mode, the lowest possible rate is one packet/second. 451/* in byte mode, the lowest possible rate is one packet/second.
@@ -425,15 +461,24 @@ static u32 xt_hashlimit_len_to_chunks(u32 len)
425} 461}
426 462
427/* Precision saver. */ 463/* Precision saver. */
428static u32 user2credits(u32 user) 464static u64 user2credits(u64 user, int revision)
429{ 465{
430 /* If multiplying would overflow... */ 466 if (revision == 1) {
431 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY_v1)) 467 /* If multiplying would overflow... */
432 /* Divide first. */ 468 if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY_v1))
433 return (user / XT_HASHLIMIT_SCALE) *\ 469 /* Divide first. */
434 HZ * CREDITS_PER_JIFFY_v1; 470 return (user / XT_HASHLIMIT_SCALE) *\
471 HZ * CREDITS_PER_JIFFY_v1;
472
473 return (user * HZ * CREDITS_PER_JIFFY_v1) \
474 / XT_HASHLIMIT_SCALE;
475 } else {
476 if (user > 0xFFFFFFFFFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
477 return (user / XT_HASHLIMIT_SCALE_v2) *\
478 HZ * CREDITS_PER_JIFFY;
435 479
436 return (user * HZ * CREDITS_PER_JIFFY_v1) / XT_HASHLIMIT_SCALE; 480 return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE_v2;
481 }
437} 482}
438 483
439static u32 user2credits_byte(u32 user) 484static u32 user2credits_byte(u32 user)
@@ -443,10 +488,11 @@ static u32 user2credits_byte(u32 user)
443 return (u32) (us >> 32); 488 return (u32) (us >> 32);
444} 489}
445 490
446static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now, u32 mode) 491static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now,
492 u32 mode, int revision)
447{ 493{
448 unsigned long delta = now - dh->rateinfo.prev; 494 unsigned long delta = now - dh->rateinfo.prev;
449 u32 cap; 495 u64 cap, cpj;
450 496
451 if (delta == 0) 497 if (delta == 0)
452 return; 498 return;
@@ -454,7 +500,7 @@ static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now, u32 mode)
454 dh->rateinfo.prev = now; 500 dh->rateinfo.prev = now;
455 501
456 if (mode & XT_HASHLIMIT_BYTES) { 502 if (mode & XT_HASHLIMIT_BYTES) {
457 u32 tmp = dh->rateinfo.credit; 503 u64 tmp = dh->rateinfo.credit;
458 dh->rateinfo.credit += CREDITS_PER_JIFFY_BYTES * delta; 504 dh->rateinfo.credit += CREDITS_PER_JIFFY_BYTES * delta;
459 cap = CREDITS_PER_JIFFY_BYTES * HZ; 505 cap = CREDITS_PER_JIFFY_BYTES * HZ;
460 if (tmp >= dh->rateinfo.credit) {/* overflow */ 506 if (tmp >= dh->rateinfo.credit) {/* overflow */
@@ -462,7 +508,9 @@ static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now, u32 mode)
462 return; 508 return;
463 } 509 }
464 } else { 510 } else {
465 dh->rateinfo.credit += delta * CREDITS_PER_JIFFY_v1; 511 cpj = (revision == 1) ?
512 CREDITS_PER_JIFFY_v1 : CREDITS_PER_JIFFY;
513 dh->rateinfo.credit += delta * cpj;
466 cap = dh->rateinfo.credit_cap; 514 cap = dh->rateinfo.credit_cap;
467 } 515 }
468 if (dh->rateinfo.credit > cap) 516 if (dh->rateinfo.credit > cap)
@@ -470,7 +518,7 @@ static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now, u32 mode)
470} 518}
471 519
472static void rateinfo_init(struct dsthash_ent *dh, 520static void rateinfo_init(struct dsthash_ent *dh,
473 struct xt_hashlimit_htable *hinfo) 521 struct xt_hashlimit_htable *hinfo, int revision)
474{ 522{
475 dh->rateinfo.prev = jiffies; 523 dh->rateinfo.prev = jiffies;
476 if (hinfo->cfg.mode & XT_HASHLIMIT_BYTES) { 524 if (hinfo->cfg.mode & XT_HASHLIMIT_BYTES) {
@@ -479,8 +527,8 @@ static void rateinfo_init(struct dsthash_ent *dh,
479 dh->rateinfo.credit_cap = hinfo->cfg.burst; 527 dh->rateinfo.credit_cap = hinfo->cfg.burst;
480 } else { 528 } else {
481 dh->rateinfo.credit = user2credits(hinfo->cfg.avg * 529 dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
482 hinfo->cfg.burst); 530 hinfo->cfg.burst, revision);
483 dh->rateinfo.cost = user2credits(hinfo->cfg.avg); 531 dh->rateinfo.cost = user2credits(hinfo->cfg.avg, revision);
484 dh->rateinfo.credit_cap = dh->rateinfo.credit; 532 dh->rateinfo.credit_cap = dh->rateinfo.credit;
485 } 533 }
486} 534}
@@ -604,15 +652,15 @@ static u32 hashlimit_byte_cost(unsigned int len, struct dsthash_ent *dh)
604} 652}
605 653
606static bool 654static bool
607hashlimit_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) 655hashlimit_mt_common(const struct sk_buff *skb, struct xt_action_param *par,
656 struct xt_hashlimit_htable *hinfo,
657 const struct hashlimit_cfg2 *cfg, int revision)
608{ 658{
609 const struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
610 struct xt_hashlimit_htable *hinfo = info->hinfo;
611 unsigned long now = jiffies; 659 unsigned long now = jiffies;
612 struct dsthash_ent *dh; 660 struct dsthash_ent *dh;
613 struct dsthash_dst dst; 661 struct dsthash_dst dst;
614 bool race = false; 662 bool race = false;
615 u32 cost; 663 u64 cost;
616 664
617 if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0) 665 if (hashlimit_init_dst(hinfo, &dst, skb, par->thoff) < 0)
618 goto hotdrop; 666 goto hotdrop;
@@ -627,18 +675,18 @@ hashlimit_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
627 } else if (race) { 675 } else if (race) {
628 /* Already got an entry, update expiration timeout */ 676 /* Already got an entry, update expiration timeout */
629 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); 677 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
630 rateinfo_recalc(dh, now, hinfo->cfg.mode); 678 rateinfo_recalc(dh, now, hinfo->cfg.mode, revision);
631 } else { 679 } else {
632 dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire); 680 dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
633 rateinfo_init(dh, hinfo); 681 rateinfo_init(dh, hinfo, revision);
634 } 682 }
635 } else { 683 } else {
636 /* update expiration timeout */ 684 /* update expiration timeout */
637 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire); 685 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
638 rateinfo_recalc(dh, now, hinfo->cfg.mode); 686 rateinfo_recalc(dh, now, hinfo->cfg.mode, revision);
639 } 687 }
640 688
641 if (info->cfg.mode & XT_HASHLIMIT_BYTES) 689 if (cfg->mode & XT_HASHLIMIT_BYTES)
642 cost = hashlimit_byte_cost(skb->len, dh); 690 cost = hashlimit_byte_cost(skb->len, dh);
643 else 691 else
644 cost = dh->rateinfo.cost; 692 cost = dh->rateinfo.cost;
@@ -648,70 +696,126 @@ hashlimit_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
648 dh->rateinfo.credit -= cost; 696 dh->rateinfo.credit -= cost;
649 spin_unlock(&dh->lock); 697 spin_unlock(&dh->lock);
650 rcu_read_unlock_bh(); 698 rcu_read_unlock_bh();
651 return !(info->cfg.mode & XT_HASHLIMIT_INVERT); 699 return !(cfg->mode & XT_HASHLIMIT_INVERT);
652 } 700 }
653 701
654 spin_unlock(&dh->lock); 702 spin_unlock(&dh->lock);
655 rcu_read_unlock_bh(); 703 rcu_read_unlock_bh();
656 /* default match is underlimit - so over the limit, we need to invert */ 704 /* default match is underlimit - so over the limit, we need to invert */
657 return info->cfg.mode & XT_HASHLIMIT_INVERT; 705 return cfg->mode & XT_HASHLIMIT_INVERT;
658 706
659 hotdrop: 707 hotdrop:
660 par->hotdrop = true; 708 par->hotdrop = true;
661 return false; 709 return false;
662} 710}
663 711
664static int hashlimit_mt_check_v1(const struct xt_mtchk_param *par) 712static bool
713hashlimit_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
714{
715 const struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
716 struct xt_hashlimit_htable *hinfo = info->hinfo;
717 struct hashlimit_cfg2 cfg = {};
718 int ret;
719
720 ret = cfg_copy(&cfg, (void *)&info->cfg, 1);
721
722 if (ret)
723 return ret;
724
725 return hashlimit_mt_common(skb, par, hinfo, &cfg, 1);
726}
727
728static bool
729hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par)
730{
731 const struct xt_hashlimit_mtinfo2 *info = par->matchinfo;
732 struct xt_hashlimit_htable *hinfo = info->hinfo;
733
734 return hashlimit_mt_common(skb, par, hinfo, &info->cfg, 2);
735}
736
737static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,
738 struct xt_hashlimit_htable **hinfo,
739 struct hashlimit_cfg2 *cfg,
740 const char *name, int revision)
665{ 741{
666 struct net *net = par->net; 742 struct net *net = par->net;
667 struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
668 int ret; 743 int ret;
669 744
670 if (info->cfg.gc_interval == 0 || info->cfg.expire == 0) 745 if (cfg->gc_interval == 0 || cfg->expire == 0)
671 return -EINVAL;
672 if (info->name[sizeof(info->name)-1] != '\0')
673 return -EINVAL; 746 return -EINVAL;
674 if (par->family == NFPROTO_IPV4) { 747 if (par->family == NFPROTO_IPV4) {
675 if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32) 748 if (cfg->srcmask > 32 || cfg->dstmask > 32)
676 return -EINVAL; 749 return -EINVAL;
677 } else { 750 } else {
678 if (info->cfg.srcmask > 128 || info->cfg.dstmask > 128) 751 if (cfg->srcmask > 128 || cfg->dstmask > 128)
679 return -EINVAL; 752 return -EINVAL;
680 } 753 }
681 754
682 if (info->cfg.mode & ~XT_HASHLIMIT_ALL) { 755 if (cfg->mode & ~XT_HASHLIMIT_ALL) {
683 pr_info("Unknown mode mask %X, kernel too old?\n", 756 pr_info("Unknown mode mask %X, kernel too old?\n",
684 info->cfg.mode); 757 cfg->mode);
685 return -EINVAL; 758 return -EINVAL;
686 } 759 }
687 760
688 /* Check for overflow. */ 761 /* Check for overflow. */
689 if (info->cfg.mode & XT_HASHLIMIT_BYTES) { 762 if (cfg->mode & XT_HASHLIMIT_BYTES) {
690 if (user2credits_byte(info->cfg.avg) == 0) { 763 if (user2credits_byte(cfg->avg) == 0) {
691 pr_info("overflow, rate too high: %u\n", info->cfg.avg); 764 pr_info("overflow, rate too high: %llu\n", cfg->avg);
692 return -EINVAL; 765 return -EINVAL;
693 } 766 }
694 } else if (info->cfg.burst == 0 || 767 } else if (cfg->burst == 0 ||
695 user2credits(info->cfg.avg * info->cfg.burst) < 768 user2credits(cfg->avg * cfg->burst, revision) <
696 user2credits(info->cfg.avg)) { 769 user2credits(cfg->avg, revision)) {
697 pr_info("overflow, try lower: %u/%u\n", 770 pr_info("overflow, try lower: %llu/%llu\n",
698 info->cfg.avg, info->cfg.burst); 771 cfg->avg, cfg->burst);
699 return -ERANGE; 772 return -ERANGE;
700 } 773 }
701 774
702 mutex_lock(&hashlimit_mutex); 775 mutex_lock(&hashlimit_mutex);
703 info->hinfo = htable_find_get(net, info->name, par->family); 776 *hinfo = htable_find_get(net, name, par->family);
704 if (info->hinfo == NULL) { 777 if (*hinfo == NULL) {
705 ret = htable_create_v1(net, info, par->family); 778 ret = htable_create(net, cfg, name, par->family,
779 hinfo, revision);
706 if (ret < 0) { 780 if (ret < 0) {
707 mutex_unlock(&hashlimit_mutex); 781 mutex_unlock(&hashlimit_mutex);
708 return ret; 782 return ret;
709 } 783 }
710 } 784 }
711 mutex_unlock(&hashlimit_mutex); 785 mutex_unlock(&hashlimit_mutex);
786
712 return 0; 787 return 0;
713} 788}
714 789
790static int hashlimit_mt_check_v1(const struct xt_mtchk_param *par)
791{
792 struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
793 struct hashlimit_cfg2 cfg = {};
794 int ret;
795
796 if (info->name[sizeof(info->name) - 1] != '\0')
797 return -EINVAL;
798
799 ret = cfg_copy(&cfg, (void *)&info->cfg, 1);
800
801 if (ret)
802 return ret;
803
804 return hashlimit_mt_check_common(par, &info->hinfo,
805 &cfg, info->name, 1);
806}
807
808static int hashlimit_mt_check(const struct xt_mtchk_param *par)
809{
810 struct xt_hashlimit_mtinfo2 *info = par->matchinfo;
811
812 if (info->name[sizeof(info->name) - 1] != '\0')
813 return -EINVAL;
814
815 return hashlimit_mt_check_common(par, &info->hinfo, &info->cfg,
816 info->name, 2);
817}
818
715static void hashlimit_mt_destroy_v1(const struct xt_mtdtor_param *par) 819static void hashlimit_mt_destroy_v1(const struct xt_mtdtor_param *par)
716{ 820{
717 const struct xt_hashlimit_mtinfo1 *info = par->matchinfo; 821 const struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
@@ -719,6 +823,13 @@ static void hashlimit_mt_destroy_v1(const struct xt_mtdtor_param *par)
719 htable_put(info->hinfo); 823 htable_put(info->hinfo);
720} 824}
721 825
826static void hashlimit_mt_destroy(const struct xt_mtdtor_param *par)
827{
828 const struct xt_hashlimit_mtinfo2 *info = par->matchinfo;
829
830 htable_put(info->hinfo);
831}
832
722static struct xt_match hashlimit_mt_reg[] __read_mostly = { 833static struct xt_match hashlimit_mt_reg[] __read_mostly = {
723 { 834 {
724 .name = "hashlimit", 835 .name = "hashlimit",
@@ -730,6 +841,16 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = {
730 .destroy = hashlimit_mt_destroy_v1, 841 .destroy = hashlimit_mt_destroy_v1,
731 .me = THIS_MODULE, 842 .me = THIS_MODULE,
732 }, 843 },
844 {
845 .name = "hashlimit",
846 .revision = 2,
847 .family = NFPROTO_IPV4,
848 .match = hashlimit_mt,
849 .matchsize = sizeof(struct xt_hashlimit_mtinfo2),
850 .checkentry = hashlimit_mt_check,
851 .destroy = hashlimit_mt_destroy,
852 .me = THIS_MODULE,
853 },
733#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 854#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
734 { 855 {
735 .name = "hashlimit", 856 .name = "hashlimit",
@@ -741,6 +862,16 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = {
741 .destroy = hashlimit_mt_destroy_v1, 862 .destroy = hashlimit_mt_destroy_v1,
742 .me = THIS_MODULE, 863 .me = THIS_MODULE,
743 }, 864 },
865 {
866 .name = "hashlimit",
867 .revision = 2,
868 .family = NFPROTO_IPV6,
869 .match = hashlimit_mt,
870 .matchsize = sizeof(struct xt_hashlimit_mtinfo2),
871 .checkentry = hashlimit_mt_check,
872 .destroy = hashlimit_mt_destroy,
873 .me = THIS_MODULE,
874 },
744#endif 875#endif
745}; 876};
746 877
@@ -787,18 +918,12 @@ static void dl_seq_stop(struct seq_file *s, void *v)
787 spin_unlock_bh(&htable->lock); 918 spin_unlock_bh(&htable->lock);
788} 919}
789 920
790static int dl_seq_real_show_v1(struct dsthash_ent *ent, u_int8_t family, 921static void dl_seq_print(struct dsthash_ent *ent, u_int8_t family,
791 struct seq_file *s) 922 struct seq_file *s)
792{ 923{
793 const struct xt_hashlimit_htable *ht = s->private;
794
795 spin_lock(&ent->lock);
796 /* recalculate to show accurate numbers */
797 rateinfo_recalc(ent, jiffies, ht->cfg.mode);
798
799 switch (family) { 924 switch (family) {
800 case NFPROTO_IPV4: 925 case NFPROTO_IPV4:
801 seq_printf(s, "%ld %pI4:%u->%pI4:%u %u %u %u\n", 926 seq_printf(s, "%ld %pI4:%u->%pI4:%u %llu %llu %llu\n",
802 (long)(ent->expires - jiffies)/HZ, 927 (long)(ent->expires - jiffies)/HZ,
803 &ent->dst.ip.src, 928 &ent->dst.ip.src,
804 ntohs(ent->dst.src_port), 929 ntohs(ent->dst.src_port),
@@ -809,7 +934,7 @@ static int dl_seq_real_show_v1(struct dsthash_ent *ent, u_int8_t family,
809 break; 934 break;
810#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 935#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
811 case NFPROTO_IPV6: 936 case NFPROTO_IPV6:
812 seq_printf(s, "%ld %pI6:%u->%pI6:%u %u %u %u\n", 937 seq_printf(s, "%ld %pI6:%u->%pI6:%u %llu %llu %llu\n",
813 (long)(ent->expires - jiffies)/HZ, 938 (long)(ent->expires - jiffies)/HZ,
814 &ent->dst.ip6.src, 939 &ent->dst.ip6.src,
815 ntohs(ent->dst.src_port), 940 ntohs(ent->dst.src_port),
@@ -822,6 +947,34 @@ static int dl_seq_real_show_v1(struct dsthash_ent *ent, u_int8_t family,
822 default: 947 default:
823 BUG(); 948 BUG();
824 } 949 }
950}
951
952static int dl_seq_real_show_v1(struct dsthash_ent *ent, u_int8_t family,
953 struct seq_file *s)
954{
955 const struct xt_hashlimit_htable *ht = s->private;
956
957 spin_lock(&ent->lock);
958 /* recalculate to show accurate numbers */
959 rateinfo_recalc(ent, jiffies, ht->cfg.mode, 1);
960
961 dl_seq_print(ent, family, s);
962
963 spin_unlock(&ent->lock);
964 return seq_has_overflowed(s);
965}
966
967static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family,
968 struct seq_file *s)
969{
970 const struct xt_hashlimit_htable *ht = s->private;
971
972 spin_lock(&ent->lock);
973 /* recalculate to show accurate numbers */
974 rateinfo_recalc(ent, jiffies, ht->cfg.mode, 2);
975
976 dl_seq_print(ent, family, s);
977
825 spin_unlock(&ent->lock); 978 spin_unlock(&ent->lock);
826 return seq_has_overflowed(s); 979 return seq_has_overflowed(s);
827} 980}
@@ -840,6 +993,20 @@ static int dl_seq_show_v1(struct seq_file *s, void *v)
840 return 0; 993 return 0;
841} 994}
842 995
996static int dl_seq_show(struct seq_file *s, void *v)
997{
998 struct xt_hashlimit_htable *htable = s->private;
999 unsigned int *bucket = (unsigned int *)v;
1000 struct dsthash_ent *ent;
1001
1002 if (!hlist_empty(&htable->hash[*bucket])) {
1003 hlist_for_each_entry(ent, &htable->hash[*bucket], node)
1004 if (dl_seq_real_show(ent, htable->family, s))
1005 return -1;
1006 }
1007 return 0;
1008}
1009
843static const struct seq_operations dl_seq_ops_v1 = { 1010static const struct seq_operations dl_seq_ops_v1 = {
844 .start = dl_seq_start, 1011 .start = dl_seq_start,
845 .next = dl_seq_next, 1012 .next = dl_seq_next,
@@ -847,6 +1014,13 @@ static const struct seq_operations dl_seq_ops_v1 = {
847 .show = dl_seq_show_v1 1014 .show = dl_seq_show_v1
848}; 1015};
849 1016
1017static const struct seq_operations dl_seq_ops = {
1018 .start = dl_seq_start,
1019 .next = dl_seq_next,
1020 .stop = dl_seq_stop,
1021 .show = dl_seq_show
1022};
1023
850static int dl_proc_open_v1(struct inode *inode, struct file *file) 1024static int dl_proc_open_v1(struct inode *inode, struct file *file)
851{ 1025{
852 int ret = seq_open(file, &dl_seq_ops_v1); 1026 int ret = seq_open(file, &dl_seq_ops_v1);
@@ -858,6 +1032,18 @@ static int dl_proc_open_v1(struct inode *inode, struct file *file)
858 return ret; 1032 return ret;
859} 1033}
860 1034
1035static int dl_proc_open(struct inode *inode, struct file *file)
1036{
1037 int ret = seq_open(file, &dl_seq_ops);
1038
1039 if (!ret) {
1040 struct seq_file *sf = file->private_data;
1041
1042 sf->private = PDE_DATA(inode);
1043 }
1044 return ret;
1045}
1046
861static const struct file_operations dl_file_ops_v1 = { 1047static const struct file_operations dl_file_ops_v1 = {
862 .owner = THIS_MODULE, 1048 .owner = THIS_MODULE,
863 .open = dl_proc_open_v1, 1049 .open = dl_proc_open_v1,
@@ -866,6 +1052,14 @@ static const struct file_operations dl_file_ops_v1 = {
866 .release = seq_release 1052 .release = seq_release
867}; 1053};
868 1054
1055static const struct file_operations dl_file_ops = {
1056 .owner = THIS_MODULE,
1057 .open = dl_proc_open,
1058 .read = seq_read,
1059 .llseek = seq_lseek,
1060 .release = seq_release
1061};
1062
869static int __net_init hashlimit_proc_net_init(struct net *net) 1063static int __net_init hashlimit_proc_net_init(struct net *net)
870{ 1064{
871 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net); 1065 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);