aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJan Engelhardt <jengelh@computergmbh.de>2008-01-31 07:48:13 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:28:04 -0500
commit09e410def6432458c7d7e771a1807b157f4c2577 (patch)
tree409cb903573639d08b3dbe0418477a0ac6e87eee /net
parentd33b7c06bd721e21534c120d1c4a5944dc3eb9ce (diff)
[NETFILTER]: xt_hashlimit match, revision 1
Introduces the xt_hashlimit match revision 1. It adds support for kernel-level inversion and grouping source and/or destination IP addresses, allowing to limit on a per-subnet basis. While this would technically obsolete xt_limit, xt_hashlimit is a more expensive due to the hashbucketing. Kernel-level inversion: Previously you had to do user-level inversion: iptables -N foo iptables -A foo -m hashlimit --hashlimit(-upto) 5/s -j RETURN iptables -A foo -j DROP iptables -A INPUT -j foo now it is simpler: iptables -A INPUT -m hashlimit --hashlimit-over 5/s -j DROP Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/xt_hashlimit.c322
1 files changed, 286 insertions, 36 deletions
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index b224b8f719a4..54aaf5bac2d7 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -1,9 +1,9 @@
1/* iptables match extension to limit the number of packets per second 1/*
2 * seperately for each hashbucket (sourceip/sourceport/dstip/dstport) 2 * xt_hashlimit - Netfilter module to limit the number of packets per time
3 * seperately for each hashbucket (sourceip/sourceport/dstip/dstport)
3 * 4 *
4 * (C) 2003-2004 by Harald Welte <laforge@netfilter.org> 5 * (C) 2003-2004 by Harald Welte <laforge@netfilter.org>
5 * 6 * Copyright © CC Computer Consultants GmbH, 2007 - 2008
6 * $Id: ipt_hashlimit.c 3244 2004-10-20 16:24:29Z laforge@netfilter.org $
7 * 7 *
8 * Development of this code was funded by Astaro AG, http://www.astaro.com/ 8 * Development of this code was funded by Astaro AG, http://www.astaro.com/
9 */ 9 */
@@ -35,6 +35,7 @@
35 35
36MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
37MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 37MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
38MODULE_AUTHOR("Jan Engelhardt <jengelh@computergmbh.de>");
38MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match"); 39MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match");
39MODULE_ALIAS("ipt_hashlimit"); 40MODULE_ALIAS("ipt_hashlimit");
40MODULE_ALIAS("ip6t_hashlimit"); 41MODULE_ALIAS("ip6t_hashlimit");
@@ -57,7 +58,7 @@ struct dsthash_dst {
57 __be32 dst[4]; 58 __be32 dst[4];
58 } ip6; 59 } ip6;
59#endif 60#endif
60 } addr; 61 };
61 __be16 src_port; 62 __be16 src_port;
62 __be16 dst_port; 63 __be16 dst_port;
63}; 64};
@@ -81,7 +82,7 @@ struct xt_hashlimit_htable {
81 atomic_t use; 82 atomic_t use;
82 int family; 83 int family;
83 84
84 struct hashlimit_cfg cfg; /* config */ 85 struct hashlimit_cfg1 cfg; /* config */
85 86
86 /* used internally */ 87 /* used internally */
87 spinlock_t lock; /* lock for list_head */ 88 spinlock_t lock; /* lock for list_head */
@@ -184,7 +185,7 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent)
184} 185}
185static void htable_gc(unsigned long htlong); 186static void htable_gc(unsigned long htlong);
186 187
187static int htable_create(struct xt_hashlimit_info *minfo, int family) 188static int htable_create_v0(struct xt_hashlimit_info *minfo, int family)
188{ 189{
189 struct xt_hashlimit_htable *hinfo; 190 struct xt_hashlimit_htable *hinfo;
190 unsigned int size; 191 unsigned int size;
@@ -210,7 +211,18 @@ static int htable_create(struct xt_hashlimit_info *minfo, int family)
210 minfo->hinfo = hinfo; 211 minfo->hinfo = hinfo;
211 212
212 /* copy match config into hashtable config */ 213 /* copy match config into hashtable config */
213 memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg)); 214 hinfo->cfg.mode = minfo->cfg.mode;
215 hinfo->cfg.avg = minfo->cfg.avg;
216 hinfo->cfg.burst = minfo->cfg.burst;
217 hinfo->cfg.max = minfo->cfg.max;
218 hinfo->cfg.gc_interval = minfo->cfg.gc_interval;
219 hinfo->cfg.expire = minfo->cfg.expire;
220
221 if (family == AF_INET)
222 hinfo->cfg.srcmask = hinfo->cfg.dstmask = 32;
223 else
224 hinfo->cfg.srcmask = hinfo->cfg.dstmask = 128;
225
214 hinfo->cfg.size = size; 226 hinfo->cfg.size = size;
215 if (!hinfo->cfg.max) 227 if (!hinfo->cfg.max)
216 hinfo->cfg.max = 8 * hinfo->cfg.size; 228 hinfo->cfg.max = 8 * hinfo->cfg.size;
@@ -246,6 +258,70 @@ static int htable_create(struct xt_hashlimit_info *minfo, int family)
246 return 0; 258 return 0;
247} 259}
248 260
261static int htable_create(struct xt_hashlimit_mtinfo1 *minfo,
262 unsigned int family)
263{
264 struct xt_hashlimit_htable *hinfo;
265 unsigned int size;
266 unsigned int i;
267
268 if (minfo->cfg.size) {
269 size = minfo->cfg.size;
270 } else {
271 size = (num_physpages << PAGE_SHIFT) / 16384 /
272 sizeof(struct list_head);
273 if (num_physpages > 1024 * 1024 * 1024 / PAGE_SIZE)
274 size = 8192;
275 if (size < 16)
276 size = 16;
277 }
278 /* FIXME: don't use vmalloc() here or anywhere else -HW */
279 hinfo = vmalloc(sizeof(struct xt_hashlimit_htable) +
280 sizeof(struct list_head) * size);
281 if (hinfo == NULL) {
282 printk(KERN_ERR "xt_hashlimit: unable to create hashtable\n");
283 return -1;
284 }
285 minfo->hinfo = hinfo;
286
287 /* copy match config into hashtable config */
288 memcpy(&hinfo->cfg, &minfo->cfg, sizeof(hinfo->cfg));
289 hinfo->cfg.size = size;
290 if (hinfo->cfg.max == 0)
291 hinfo->cfg.max = 8 * hinfo->cfg.size;
292 else if (hinfo->cfg.max < hinfo->cfg.size)
293 hinfo->cfg.max = hinfo->cfg.size;
294
295 for (i = 0; i < hinfo->cfg.size; i++)
296 INIT_HLIST_HEAD(&hinfo->hash[i]);
297
298 atomic_set(&hinfo->use, 1);
299 hinfo->count = 0;
300 hinfo->family = family;
301 hinfo->rnd_initialized = 0;
302 spin_lock_init(&hinfo->lock);
303
304 hinfo->pde = create_proc_entry(minfo->name, 0,
305 family == AF_INET ? hashlimit_procdir4 :
306 hashlimit_procdir6);
307 if (hinfo->pde == NULL) {
308 vfree(hinfo);
309 return -1;
310 }
311 hinfo->pde->proc_fops = &dl_file_ops;
312 hinfo->pde->data = hinfo;
313
314 setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo);
315 hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval);
316 add_timer(&hinfo->timer);
317
318 spin_lock_bh(&hashlimit_lock);
319 hlist_add_head(&hinfo->node, &hashlimit_htables);
320 spin_unlock_bh(&hashlimit_lock);
321
322 return 0;
323}
324
249static bool select_all(const struct xt_hashlimit_htable *ht, 325static bool select_all(const struct xt_hashlimit_htable *ht,
250 const struct dsthash_ent *he) 326 const struct dsthash_ent *he)
251{ 327{
@@ -388,6 +464,46 @@ static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now)
388 dh->rateinfo.prev = now; 464 dh->rateinfo.prev = now;
389} 465}
390 466
467static inline __be32 maskl(__be32 a, unsigned int l)
468{
469 return htonl(ntohl(a) & ~(~(u_int32_t)0 >> l));
470}
471
472static void hashlimit_ipv6_mask(__be32 *i, unsigned int p)
473{
474 switch (p) {
475 case 0:
476 i[0] = i[1] = 0;
477 i[2] = i[3] = 0;
478 break;
479 case 1 ... 31:
480 i[0] = maskl(i[0], p);
481 i[1] = i[2] = i[3] = 0;
482 break;
483 case 32:
484 i[1] = i[2] = i[3] = 0;
485 break;
486 case 33 ... 63:
487 i[1] = maskl(i[1], p - 32);
488 i[2] = i[3] = 0;
489 break;
490 case 64:
491 i[2] = i[3] = 0;
492 break;
493 case 65 ... 95:
494 i[2] = maskl(i[2], p - 64);
495 i[3] = 0;
496 case 96:
497 i[3] = 0;
498 break;
499 case 97 ... 127:
500 i[3] = maskl(i[3], p - 96);
501 break;
502 case 128:
503 break;
504 }
505}
506
391static int 507static int
392hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo, 508hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
393 struct dsthash_dst *dst, 509 struct dsthash_dst *dst,
@@ -401,9 +517,11 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
401 switch (hinfo->family) { 517 switch (hinfo->family) {
402 case AF_INET: 518 case AF_INET:
403 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) 519 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP)
404 dst->addr.ip.dst = ip_hdr(skb)->daddr; 520 dst->ip.dst = maskl(ip_hdr(skb)->daddr,
521 hinfo->cfg.dstmask);
405 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) 522 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP)
406 dst->addr.ip.src = ip_hdr(skb)->saddr; 523 dst->ip.src = maskl(ip_hdr(skb)->saddr,
524 hinfo->cfg.srcmask);
407 525
408 if (!(hinfo->cfg.mode & 526 if (!(hinfo->cfg.mode &
409 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) 527 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
@@ -412,12 +530,16 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
412 break; 530 break;
413#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) 531#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
414 case AF_INET6: 532 case AF_INET6:
415 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) 533 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_DIP) {
416 memcpy(&dst->addr.ip6.dst, &ipv6_hdr(skb)->daddr, 534 memcpy(&dst->ip6.dst, &ipv6_hdr(skb)->daddr,
417 sizeof(dst->addr.ip6.dst)); 535 sizeof(dst->ip6.dst));
418 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) 536 hashlimit_ipv6_mask(dst->ip6.dst, hinfo->cfg.dstmask);
419 memcpy(&dst->addr.ip6.src, &ipv6_hdr(skb)->saddr, 537 }
420 sizeof(dst->addr.ip6.src)); 538 if (hinfo->cfg.mode & XT_HASHLIMIT_HASH_SIP) {
539 memcpy(&dst->ip6.src, &ipv6_hdr(skb)->saddr,
540 sizeof(dst->ip6.src));
541 hashlimit_ipv6_mask(dst->ip6.src, hinfo->cfg.srcmask);
542 }
421 543
422 if (!(hinfo->cfg.mode & 544 if (!(hinfo->cfg.mode &
423 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT))) 545 (XT_HASHLIMIT_HASH_DPT | XT_HASHLIMIT_HASH_SPT)))
@@ -457,10 +579,10 @@ hashlimit_init_dst(const struct xt_hashlimit_htable *hinfo,
457} 579}
458 580
459static bool 581static bool
460hashlimit_mt(const struct sk_buff *skb, const struct net_device *in, 582hashlimit_mt_v0(const struct sk_buff *skb, const struct net_device *in,
461 const struct net_device *out, const struct xt_match *match, 583 const struct net_device *out, const struct xt_match *match,
462 const void *matchinfo, int offset, unsigned int protoff, 584 const void *matchinfo, int offset, unsigned int protoff,
463 bool *hotdrop) 585 bool *hotdrop)
464{ 586{
465 const struct xt_hashlimit_info *r = 587 const struct xt_hashlimit_info *r =
466 ((const struct xt_hashlimit_info *)matchinfo)->u.master; 588 ((const struct xt_hashlimit_info *)matchinfo)->u.master;
@@ -512,9 +634,62 @@ hotdrop:
512} 634}
513 635
514static bool 636static bool
515hashlimit_mt_check(const char *tablename, const void *inf, 637hashlimit_mt(const struct sk_buff *skb, const struct net_device *in,
516 const struct xt_match *match, void *matchinfo, 638 const struct net_device *out, const struct xt_match *match,
517 unsigned int hook_mask) 639 const void *matchinfo, int offset, unsigned int protoff,
640 bool *hotdrop)
641{
642 const struct xt_hashlimit_mtinfo1 *info = matchinfo;
643 struct xt_hashlimit_htable *hinfo = info->hinfo;
644 unsigned long now = jiffies;
645 struct dsthash_ent *dh;
646 struct dsthash_dst dst;
647
648 if (hashlimit_init_dst(hinfo, &dst, skb, protoff) < 0)
649 goto hotdrop;
650
651 spin_lock_bh(&hinfo->lock);
652 dh = dsthash_find(hinfo, &dst);
653 if (dh == NULL) {
654 dh = dsthash_alloc_init(hinfo, &dst);
655 if (dh == NULL) {
656 spin_unlock_bh(&hinfo->lock);
657 goto hotdrop;
658 }
659
660 dh->expires = jiffies + msecs_to_jiffies(hinfo->cfg.expire);
661 dh->rateinfo.prev = jiffies;
662 dh->rateinfo.credit = user2credits(hinfo->cfg.avg *
663 hinfo->cfg.burst);
664 dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg *
665 hinfo->cfg.burst);
666 dh->rateinfo.cost = user2credits(hinfo->cfg.avg);
667 } else {
668 /* update expiration timeout */
669 dh->expires = now + msecs_to_jiffies(hinfo->cfg.expire);
670 rateinfo_recalc(dh, now);
671 }
672
673 if (dh->rateinfo.credit >= dh->rateinfo.cost) {
674 /* below the limit */
675 dh->rateinfo.credit -= dh->rateinfo.cost;
676 spin_unlock_bh(&hinfo->lock);
677 return !(info->cfg.mode & XT_HASHLIMIT_INVERT);
678 }
679
680 spin_unlock_bh(&hinfo->lock);
681 /* default match is underlimit - so over the limit, we need to invert */
682 return info->cfg.mode & XT_HASHLIMIT_INVERT;
683
684 hotdrop:
685 *hotdrop = true;
686 return false;
687}
688
689static bool
690hashlimit_mt_check_v0(const char *tablename, const void *inf,
691 const struct xt_match *match, void *matchinfo,
692 unsigned int hook_mask)
518{ 693{
519 struct xt_hashlimit_info *r = matchinfo; 694 struct xt_hashlimit_info *r = matchinfo;
520 695
@@ -546,7 +721,7 @@ hashlimit_mt_check(const char *tablename, const void *inf,
546 * create duplicate proc files. -HW */ 721 * create duplicate proc files. -HW */
547 mutex_lock(&hlimit_mutex); 722 mutex_lock(&hlimit_mutex);
548 r->hinfo = htable_find_get(r->name, match->family); 723 r->hinfo = htable_find_get(r->name, match->family);
549 if (!r->hinfo && htable_create(r, match->family) != 0) { 724 if (!r->hinfo && htable_create_v0(r, match->family) != 0) {
550 mutex_unlock(&hlimit_mutex); 725 mutex_unlock(&hlimit_mutex);
551 return false; 726 return false;
552 } 727 }
@@ -557,14 +732,68 @@ hashlimit_mt_check(const char *tablename, const void *inf,
557 return true; 732 return true;
558} 733}
559 734
735static bool
736hashlimit_mt_check(const char *tablename, const void *inf,
737 const struct xt_match *match, void *matchinfo,
738 unsigned int hook_mask)
739{
740 struct xt_hashlimit_mtinfo1 *info = matchinfo;
741
742 /* Check for overflow. */
743 if (info->cfg.burst == 0 ||
744 user2credits(info->cfg.avg * info->cfg.burst) <
745 user2credits(info->cfg.avg)) {
746 printk(KERN_ERR "xt_hashlimit: overflow, try lower: %u/%u\n",
747 info->cfg.avg, info->cfg.burst);
748 return false;
749 }
750 if (info->cfg.gc_interval == 0 || info->cfg.expire == 0)
751 return false;
752 if (info->name[sizeof(info->name)-1] != '\0')
753 return false;
754 if (match->family == AF_INET) {
755 if (info->cfg.srcmask > 32 || info->cfg.dstmask > 32)
756 return false;
757 } else {
758 if (info->cfg.srcmask > 128 || info->cfg.dstmask > 128)
759 return false;
760 }
761
762 /* This is the best we've got: We cannot release and re-grab lock,
763 * since checkentry() is called before x_tables.c grabs xt_mutex.
764 * We also cannot grab the hashtable spinlock, since htable_create will
765 * call vmalloc, and that can sleep. And we cannot just re-search
766 * the list of htable's in htable_create(), since then we would
767 * create duplicate proc files. -HW */
768 mutex_lock(&hlimit_mutex);
769 info->hinfo = htable_find_get(info->name, match->family);
770 if (!info->hinfo && htable_create(info, match->family) != 0) {
771 mutex_unlock(&hlimit_mutex);
772 return false;
773 }
774 mutex_unlock(&hlimit_mutex);
775
776 /* Ugly hack: For SMP, we only want to use one set */
777 info->master = info;
778 return true;
779}
780
560static void 781static void
561hashlimit_mt_destroy(const struct xt_match *match, void *matchinfo) 782hashlimit_mt_destroy_v0(const struct xt_match *match, void *matchinfo)
562{ 783{
563 const struct xt_hashlimit_info *r = matchinfo; 784 const struct xt_hashlimit_info *r = matchinfo;
564 785
565 htable_put(r->hinfo); 786 htable_put(r->hinfo);
566} 787}
567 788
789static void
790hashlimit_mt_destroy(const struct xt_match *match, void *matchinfo)
791{
792 const struct xt_hashlimit_mtinfo1 *info = matchinfo;
793
794 htable_put(info->hinfo);
795}
796
568#ifdef CONFIG_COMPAT 797#ifdef CONFIG_COMPAT
569struct compat_xt_hashlimit_info { 798struct compat_xt_hashlimit_info {
570 char name[IFNAMSIZ]; 799 char name[IFNAMSIZ];
@@ -592,33 +821,54 @@ static int hashlimit_mt_compat_to_user(void __user *dst, void *src)
592static struct xt_match hashlimit_mt_reg[] __read_mostly = { 821static struct xt_match hashlimit_mt_reg[] __read_mostly = {
593 { 822 {
594 .name = "hashlimit", 823 .name = "hashlimit",
824 .revision = 0,
595 .family = AF_INET, 825 .family = AF_INET,
596 .match = hashlimit_mt, 826 .match = hashlimit_mt_v0,
597 .matchsize = sizeof(struct xt_hashlimit_info), 827 .matchsize = sizeof(struct xt_hashlimit_info),
598#ifdef CONFIG_COMPAT 828#ifdef CONFIG_COMPAT
599 .compatsize = sizeof(struct compat_xt_hashlimit_info), 829 .compatsize = sizeof(struct compat_xt_hashlimit_info),
600 .compat_from_user = hashlimit_mt_compat_from_user, 830 .compat_from_user = hashlimit_mt_compat_from_user,
601 .compat_to_user = hashlimit_mt_compat_to_user, 831 .compat_to_user = hashlimit_mt_compat_to_user,
602#endif 832#endif
603 .checkentry = hashlimit_mt_check, 833 .checkentry = hashlimit_mt_check_v0,
604 .destroy = hashlimit_mt_destroy, 834 .destroy = hashlimit_mt_destroy_v0,
605 .me = THIS_MODULE 835 .me = THIS_MODULE
606 }, 836 },
837 {
838 .name = "hashlimit",
839 .revision = 1,
840 .family = AF_INET,
841 .match = hashlimit_mt,
842 .matchsize = sizeof(struct xt_hashlimit_mtinfo1),
843 .checkentry = hashlimit_mt_check,
844 .destroy = hashlimit_mt_destroy,
845 .me = THIS_MODULE,
846 },
607#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) 847#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
608 { 848 {
609 .name = "hashlimit", 849 .name = "hashlimit",
610 .family = AF_INET6, 850 .family = AF_INET6,
611 .match = hashlimit_mt, 851 .match = hashlimit_mt_v0,
612 .matchsize = sizeof(struct xt_hashlimit_info), 852 .matchsize = sizeof(struct xt_hashlimit_info),
613#ifdef CONFIG_COMPAT 853#ifdef CONFIG_COMPAT
614 .compatsize = sizeof(struct compat_xt_hashlimit_info), 854 .compatsize = sizeof(struct compat_xt_hashlimit_info),
615 .compat_from_user = hashlimit_mt_compat_from_user, 855 .compat_from_user = hashlimit_mt_compat_from_user,
616 .compat_to_user = hashlimit_mt_compat_to_user, 856 .compat_to_user = hashlimit_mt_compat_to_user,
617#endif 857#endif
618 .checkentry = hashlimit_mt_check, 858 .checkentry = hashlimit_mt_check_v0,
619 .destroy = hashlimit_mt_destroy, 859 .destroy = hashlimit_mt_destroy_v0,
620 .me = THIS_MODULE 860 .me = THIS_MODULE
621 }, 861 },
862 {
863 .name = "hashlimit",
864 .revision = 1,
865 .family = AF_INET6,
866 .match = hashlimit_mt,
867 .matchsize = sizeof(struct xt_hashlimit_mtinfo1),
868 .checkentry = hashlimit_mt_check,
869 .destroy = hashlimit_mt_destroy,
870 .me = THIS_MODULE,
871 },
622#endif 872#endif
623}; 873};
624 874
@@ -678,9 +928,9 @@ static int dl_seq_real_show(struct dsthash_ent *ent, int family,
678 return seq_printf(s, "%ld %u.%u.%u.%u:%u->" 928 return seq_printf(s, "%ld %u.%u.%u.%u:%u->"
679 "%u.%u.%u.%u:%u %u %u %u\n", 929 "%u.%u.%u.%u:%u %u %u %u\n",
680 (long)(ent->expires - jiffies)/HZ, 930 (long)(ent->expires - jiffies)/HZ,
681 NIPQUAD(ent->dst.addr.ip.src), 931 NIPQUAD(ent->dst.ip.src),
682 ntohs(ent->dst.src_port), 932 ntohs(ent->dst.src_port),
683 NIPQUAD(ent->dst.addr.ip.dst), 933 NIPQUAD(ent->dst.ip.dst),
684 ntohs(ent->dst.dst_port), 934 ntohs(ent->dst.dst_port),
685 ent->rateinfo.credit, ent->rateinfo.credit_cap, 935 ent->rateinfo.credit, ent->rateinfo.credit_cap,
686 ent->rateinfo.cost); 936 ent->rateinfo.cost);
@@ -689,9 +939,9 @@ static int dl_seq_real_show(struct dsthash_ent *ent, int family,
689 return seq_printf(s, "%ld " NIP6_FMT ":%u->" 939 return seq_printf(s, "%ld " NIP6_FMT ":%u->"
690 NIP6_FMT ":%u %u %u %u\n", 940 NIP6_FMT ":%u %u %u %u\n",
691 (long)(ent->expires - jiffies)/HZ, 941 (long)(ent->expires - jiffies)/HZ,
692 NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.src), 942 NIP6(*(struct in6_addr *)&ent->dst.ip6.src),
693 ntohs(ent->dst.src_port), 943 ntohs(ent->dst.src_port),
694 NIP6(*(struct in6_addr *)&ent->dst.addr.ip6.dst), 944 NIP6(*(struct in6_addr *)&ent->dst.ip6.dst),
695 ntohs(ent->dst.dst_port), 945 ntohs(ent->dst.dst_port),
696 ent->rateinfo.credit, ent->rateinfo.credit_cap, 946 ent->rateinfo.credit, ent->rateinfo.credit_cap,
697 ent->rateinfo.cost); 947 ent->rateinfo.cost);